CPU benchmark plugin

I want to throw together a simple plugin that does nothing other then crank on the CPU, in order to provide a way to make comparison benchmarks between different DAW’s and different hardware.

Anyone have any suggestions about what might be the best way to go about doing that in an audio plugin without having to actually process any audio?

I am thinking it will have options to specify the number of threads to use(default 1), and possibly a slider to increase or decrease some aspect of it, in order to simulate typical plugins of different cpu usage. It may literally just come down to a loop and do some simple operation inside the loop and use a slider to adjust how many iterations.

Anyone have any thoughts about this?

I did a function like this to waste CPU time for a similar plugin (that can waste CPU and do other nasty stuff on purpose) :

static int64_t CPU_waster(std::mt19937& rng, double durationtowaste)
{
	std::uniform_real_distribution<double> dist(-1.0, 1.0);
	std::atomic<double> acc{ 0.0 };
	int64_t loopcount = 0;
	double t0 = Time::getMillisecondCounterHiRes();
	while (true)
	{
		double v = dist(rng);
		double temp = acc.load();
		temp += v;
		acc.store(temp);
		++loopcount;
		double t1 = Time::getMillisecondCounterHiRes();
		if (t1 >= t0 + durationtowaste)
			break;
	}
	return loopcount;
}

It’s more complicated than could be expected because I wanted to ensure the compiler doesn’t just somehow optimize the useless calculations away. You can probably make a similar one where an instance of the random generator does not need to be passed in.

Then in my processBlock I do :

void EvilPluginAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
	ScopedNoDenormals noDenormals;
    
	if (m_cpu_waste_amount > 0.0)
	{
		double bufferclocklen = 1000.0 / getSampleRate()*buffer.getNumSamples();
		double timetospend = bufferclocklen * m_cpu_waste_amount / 100.0;
		CPU_waster(m_rnd, timetospend);
	}
}

This worked pretty well for me to be able to get a variable GUI adjustable CPU load amount on the host’s audio thread.

Nice!

Newbie question here, how can I detect if the transport is playing inside processBlock so that I can only crunch the CPU while the transport is playing?

I did something already that is simpler then yours but I like yours better. One thing I noticed is that perhaps I would like it to have a ramp up period instead of the slamming the CPU suddenly when it starts. So I may program something like that into it too.

See https://docs.juce.com/master/structAudioPlayHead_1_1CurrentPositionInfo.html

1 Like

perfect thanks!

Here’s a oneliner:

inline void nop() { __asm__ ("nop"); } 

This stalls the CPU core for 1 cycle. It does nasty things to pipelines, but if you just want to do literally nothing while consuming CPU cycles, that’s why nop exists. Just call it in a loop of varying length to adjust how much load you want to consume.

nops are useful because they’re fairly consistent. For example, calling it 10x more takes just about 10x more CPU to evaluate:

http://quick-bench.com/EIT_SfkRme-EKqkK4grSCFsu31M.

The one thing to be aware of is that if you use this to benchmark overhead of DAWs calling into your plugin, you’re not going to notice a whole lot of variance when it comes to cache locality/coherence. This is just a CPU bound test. For memory you might want to try something like a one-buffer delay.

2 Likes

This is an interesting idea about making sure to hit some memory too. I haven’t written any DSP before, so that will take some homework. But thanks for the idea.

Ideally I’d like the plugin to mimic a real world plugin in terms of how it impacts the system…but with a very dependable and consistent amount of work involved. Then it can be used to compare systems, DAW’s, etc. in a consistent way.

I already discovered some really weird stuff about how LogicPro is allocating jobs to threads, not quite in the way everyone thinks it does.