Beginner optimization questions


After spending the last few months exploring JUCE, dsp, synth making and thoroughly enjoying myself, I realized that I've got to get real...I don't really know how much CPU usage my synth is using, nor do I know how to track it down. Obviously, once I know my problems, I can take steps to deal with them, but I have to know what the issues are first. 


What's the best way to get an idea of how much CPU my plugin is using? Or is that even the proper question?

For what it's worth, I'm working on a Mac.

If it were a *normal* non-audio app, I could use Instruments and find out all kinds of stuff, but I don't know the best way to do that with an audio plugin. 

One thing that triggered this topic is, I've recently started getting random loud pops every once in a while. Not very often and not all the time. I can't trace the pops to any one thing I've added recently or any specific UI interaction, however, it made me wonder about CPU usage and just how clueless I am right now. Who knows...maybe it's just El Capitan.

Which also makes me wonder about the difference of JUCE in debug mode vs JUCE in optimized mode. 

I realize this is a wandering question, but I think you pros will know what I'm talking about. ANY tips would be greatly appreciated. 

Thank you.

PS - I hope no one minds, but I'm going to cross post this in the Mac specific forum as well.




It's important that you make performance measurements with the release build without JUCE Debug. Make sure you also have enabled processor optimations for speed and that you have enabled SSE2. 

Almost every host has a CPU meter where you can compare the performance with other plugins. Check for denormalisation issues if you have huge CPU spikes, especially when the plugin has no audio output. 

After that you can use something like, if you need more details where the performance problem is. It should be free.

Hope this helps.


On a Mac, a good way to profile an app is Instruments (Xcode -> Open Developer Tool -> Instruments). There you can do many things, one of the most useful being the Time Profiler. This will record how much time and CPU resources your app spends inside every function and can be a good way to find performance bottlenecks.


This is great. Thank you.


For some reason, I assumed wrongly that because of the nature of audio software that it would be tricky or at least very difficult to use Instruments. I'll give it a shot.


But...what about for a plugin and not an app?




Install AU Lab or some other simple host, and set that as your Executable in your Profile Scheme (Product > Scheme > Edit Scheme). Now you can launch Instruments with Cmd-I, and it will load the host once you select the type of profiling you want. Then when you load an instance of your plugin in the host, Instruments will automatically see that and start measuring it. To make things even easier, in my Scheme I have an argument passed on launch that loads a save file with my plugin already added. Then it's essentially one keystroke to compile a Release build and profile it.


You can always use fixed point processing! Just kidding, that's brutal. 

One go-to DSP optimization technique is to get rid of every single trig function call and replace it with a lookup table. It's useful to have a simple class with lookups for tangent, sine, cosine, hyperbolic and arc functions as well. The majority of filters require calls to those functions, and that's where the bulk of your overhead is. Replacing those with table lookups is great. That one step will make a lot of your plugins more efficient. 

Another one if you're processing MIDI data is to make a 128 sized array. Store the note frequencies for every single MIDI note#. When a MIDI message comes in, use MidiMessage::getNoteNumber() as the index for the array. No processing required!

There are some pitfalls with optimization though. You should always use inline functions for filter coefficient updates and processing. Never split the two between threads either. If some coefficients are updated before others, or in the middle of the process function due to scheduling by the OS or optimization by the compiler it will blow the filter up. 

Multithreading is also a really good tool for optimizing (and improving perceived optimization by giving your plugin priority). But the hazard there is synchronization, and you should avoid it for things that aren't obvious to parallelize. Anything based on the FFT can be split apart pretty easily and done well, but other things like granular synthesis/granulizers where you may think it makes sense to split grains between threads can be a headache to synchronize. 

And ignoring my last paragraph, there's also a GPU sitting right there for you to use. Great for FFTs, convolution, any transform really or operation that's more or less a dot product computation (modulation matrix for example). 

float rational_tanh(x)
    if( x < -3 )
        return -1;
    else if( x > 3 )
        return 1;
        return x * ( 27 + x * x ) / ( 27 + 9 * x * x );



This was awesome help. Thank you so much!

One question: When I double click on one of my functions, it shows me assembly language, not my C++ source. Is that normal or am I missing a setting someplace? I was expecting to see my source.


Thanks again.