ITimeCallback in SingleComponentEffect problem

We have a few plug-ins that require using the SingleComponentEffect due to the large amount of data that must be shared between the processing and editing components. In order to keep the editing portion in synch, we have derived our class from ITimerCallback as well, and implemented the onTimer() callback.

But on the PC (not the Mac, at least not as far as I have seen), we are seeing some performance issues now while the transport is running. There is a lot of drawing that may be taking place while the transport runs, showing a scrolling graph of the audio data as it is processed, and recently that scrolling is causing frequent audio glitches. If we turn off the constant scrolling, then the glitches and audio drop-outs and stalls all go away. We’re not certain how this can be, since UI operations do not generally interfere with processing operations, but run on separate threads.

Specifically, what we do is respond to the onTimer() callback by regenerating the graph data into an offline context, then invalidating the graph view. This allows it to be repainted with the already prepared graphics on the next paint message.

What I am wondering is if, somehow, the SingleComponentEffect base class is actually calling the onTimer() callback on the process thread, and that is why the larger amount of drawing done during scrolling is causing such huge CPU spikes that it is stalling the process pipeline. Is this possible? If so, is there a way to prevent it?

I thought of using a separate thread to wake on intervals and call our drawing code, but I have seen previously that that causes drawing problems with multiple threads drawing at once and interfering with each other. In cases where I have encountered this (ARA), I had to simply set a flag saying that regeneration of the graph data was required, and that regeneration occurred during the normal onTimer() callback. But if I replace the onTimer() callback, then I obviously can’t rely on the it to do do the work for me that is required. So I’m kind of stuck as to how and when to regenerate the graph data (which is what is causing the CPU spike, I believe).

Does my analysis sound correct, that the onTimer() callback is causing the CPU spike because it is not on the UI thread? Or could simply taking too long to return from the onTimer() cause such a spike? And why is this only a problem on the PC? Most importantly, how might I make certain that the regeneration of the graph data does not cause these spikes?


Hmm, it seems that it is stalling the host (i.e., its main run loop), not the process thread explicitly. I am not sure why this is a problem now under VST3SDK 3.6.6, where it wasn’t a problem in earlier versions of our software. We do have more graphics to draw, but I would not think that change so significant that it suddenly becomes an issu, throwing large CPU spikes.

I thought that perhaps it is a VSTGUI issue, where certain nine-part-bitmaps now have much smaller “grow zones”, causing a significant increase in time to render those images to the offline context, but the problem occurs even with the graphics at their default (minimum) size, so I doubt that’s involved here.

Is there a way in Visual Studio to easily identify the occurrence of such a spike in a plug-in? What’s a good profiling tool for plug-ins on Windows, one that will help me identify specific information about these CPU spikes??


I found that the large CPU spikes were only in Cubase 8.5, which apparently was notorious for that.

However, I still get artifacts regularly when scrolling my graph while the audio is playing back. The CPU Usage info in the VS debugger shows the largest time taken by our processing code, but that does not seem related to this, because I get the same results whether the graph is scrolling and causing these artifacts or not. It’s still causing a stall in the host, as far as I can tell, although the CPU meter is no longer showing those big spikes.

Hi Howard,

maybe this is in some way related to VSTGUI 4.3’s GDI+ based default drawing on Windows, which is notorious for being rather slow. Try defining the VSTGUI_DIRECT2D_SUPPORT macro as 1 in your project to force VSTGUI to use direct2d as the graphics backend - this has become the default mode in 4.5 btw.