We are using JUCE to host VST3 plugins, and we’ve discovered something of a design flaw with Line 6’s popular Helix Native VST3 guitar effects plugin. A trial of the plug-in can be downloaded here: http://line6.com/software/.
The issue is pretty simple. For pretty much every buffer, and perhaps multiple times per buffer, Helix calls JUCE’s createInstance() function and creates a new IMessage. This happens at approximately line 681 of juce_VST3PluginFormat.cpp. The message object gets created, and added to the messageQueue at line 682. Later, AttributeList::setBinary is called, which calls addMessageToQueue, which finds the message in the queue and modifies it. Unfortunately nothing ever removed the message from the queue – there doesn’t even appear to be any code in JUCE that could remove a message from the queue – and at every buffer, new messages are created and stored in the queue. After 15-30 seconds of playback, there are over 15,000 messages in the queue, and soon after that audio will start stuttering because every call to AttributeList::setBinary has to search through tens of thousands of Messages to try to find the right one to modify. Meanwhile, the messageQueue just keeps growing larger and larger, and pretty soon audio playback becomes impossible.
I expect that most VST3s just reuse message objects instead of creating them over and over again. I checked to see if the Message objects were getting deleted (but not removed from the messageQueue) and it appears that the Message() destructor does not get called during playback.
This problem does not exist in Reaper, as far as we can tell. Is JUCE supposed be removing messages from the messageQueue at some point? Or perhaps our plug-in host has the responsibility to clear the messageQueue somehow? As I said, I can’t find any code that would ever remove messages from the messageQueue, but perhaps I’m just not seeing it.
I hope you can help correct this.