Plugin editor window slow to open (since JUCE 6.1 possibly?)

I could be totally wrong here… but couldn’t figure this out after a lengthy dig - just confused - I hope somebody can point me in the right direction.

I’ve noticed (but I do need to go back and rebuild against JUCE 6.07 to confirm it though), that my plugin editor window appears to take much longer to open (either AU/VST3 or standalone) recently. It takes over 1 second… but on profiling my code, the code which actually creates the new instance of my editor only takes something like a couple of milliseconds… I verified this by creating and deleting my editor within the ‘createEditor’ function multiple times (and profiling in both standalone and AU inside Ableton)… there’s a lot of dead time in that function where it appears something else with higher priority is blocking the UI thread during ‘createEditor’? (But I don’t think it’s audio processing as I’m testing with an empty patch which does almost no audio processing other than return an empty buffer and profiling the processBlock shows that it is shortly entered/exited.)
‘createEditor’ call happens after state restore… so it’s not any state restore stuff that’s holding things up… nor any background process I have since those are lower priority than the UI thread.
(edit… should add - I am currently testing on Mac OS 11.5.2, building in XCode 12.5)

(Note the text labels should read ‘new HyprSynthPluginAudioProcessorEditor’ - sorry for any confusion in the image)

The trace above is taken after a couple of times open and close the editor window…so well after the plugin is initially loaded in the DAW.

(I have a custom ‘function scoped’ profiling function that is also called in HyprSynthPluginAudioProcessorEditor constructor.)

AudioProcessorEditor* HyprSynthPluginAudioProcessor::createEditor()
{
    UI_PROFILE_FUNCTION();

#if 0 //def _DEBUG
	String paintString = "HyprSynthPluginAudioProcessor::createEditor()";
	DBG(paintString);
#endif
    
    HyprSynthPluginAudioProcessorEditor* ed = nullptr;
    
#ifdef _DEBUG // just testing long it takes...
    ed =  new HyprSynthPluginAudioProcessorEditor (*this, synthUImaster, globallooknfeel);
    
    delete ed;
    
    ed =  new HyprSynthPluginAudioProcessorEditor (*this, synthUImaster, globallooknfeel);
    
    delete ed;
    
#endif
    
     ed =  new HyprSynthPluginAudioProcessorEditor (*this, synthUImaster, globallooknfeel);
   
    return ed;
}

FYI - I just downgraded my JUCE source from 6.1.1 to 6.0.7 and now my plugin editor window (Hyperion) opens without any delay (testing in live 10 on Mac M1 Air - building in Xcode 12.5.1) - building from my latest plugin release source code (v1.12), and only changing the JUCE modules. (Small disclaimer - both these versions of JUCE are taken from official releases, but with some minor changes to the JUCE button and oversampling class - in each case, same code changes in both source sets.)

Secondly, an end user reported Mac M1 version of my latest build (built on 6.1.1) was showing double the CPU load as my prior release build (I confirmed it, but also confirmed this was not observed in the Intel Mac build of the same version - also built in Xcode 12.5.1) ;
I have just retested on Mac M1 rebuilding (release mode build) my current release/latest codebase, but with downgrade from JUCE 6.1.1 to 6.0.7, and the CPU load (actually the spare time between audio callbacks) has returned to normal (audio processing load dropping by 50%).

I don’t have any evidence as to what is causing these issues - it’s just my observation.

I will test rebuilding against JUCE 6.0.7 on my Intel based Mac mini now, to confirm if the editor window launch delay goes away in that case too.

To get to the bottom of what‘s slowing down your plugin, why not profile it? Usually, this gives you some good insight where in your code most of the time is spent.

As a quick guess: Do you use OpenGL? There was some restructuring about which gl functions are loaded after users reported that loading all available extensions at startup can take pretty long. Can’t find the relevant forum topic anymore though…

Firstly, thanks for responding.

I’m not using Open GL, only standard JUCE drawing/widgets, and yes, I am profiling but was using my own profiling functions to check things like how long the audio callback takes to process, how long it takes to restore the plugin state, and how long it takes to open the editor.
(I’m using Perfetto as a visualizer)

I’ve just rebuilt the Intel version of my plugin - again, same code base, but downgrade JUCE to 6.07 from 6.1.1 and I’m measuring the time it takes for ‘createEditor’ to complete is around 1/10th of before (and still the function itself is taking much longer than the constructor of my editor which is then returned).
(createEditor call was taking just over 1 second, now after downgrade to 6.07 about 110ms, and the constructor of my editor window that is returned takes 1.5 ms)

I may well have to use the Xcode or Visual studio profiler tools to look more closely at what could be delaying the ‘createEditor’ virtual function - it must be a higher priority thread.
I’m just wondering if there is anything that has changed since 6.07 to 6.1.1 that might cause the editor window to open more slowly.

I’m grateful for any tips on how to debug this (originally about the editor window open time), but in the immediate case I need to fix the issues for end users, so will make a new release reverting to 6.07.

For the issue of audio processing time/load on M1 with JUCE 6.1.1 vs 6.0.7 more profiling will be done, and maybe I’ll open a separate discussion thread.

Hi Wavesequencer,

do you maybe have a TreeView in your plugin with lots of nodes?
Because we noticed that the TreeView in JUCE 6.1.2 has gotten much slower, compared to JUCE 6.0.7. (Still debugging what is going on, therefore I have not yet opened a separat thread for that). In our case we have a TreeView with hundreds of nodes. With JUCE 6.0.7 that view is displayed in a fraction of a second. But in JUCE 6.1.2 it can take several seconds to show up.
As said, I am still debugging what’s going on there. Might well be an error on our end. And maybe you do not even have a TreeView. But just mentioning it, in case.

Hello @alatar
No, I am not using TreeView - regardless, all of the state restore of my node processing tree happens in the processor init (which only happens once when you load your plugin), and not when opening the editor window every time, and secondly, all of the GUI instantiation code that happens when I create an instance of a editor within the ‘createEditor’ virtual function happens in a very short space of time (1ms or so) regardless of which version of JUCE I am using… what seems to be happening is the the ‘createEditor’ call gets stalled by some other higher priority thread - so that it will only return my editor instance much later (1 second when compiled with JUCE 6.1.1).
I will have to profile more deeply of course, but at first it looks like this is nothing to do with any of my plugin code implementation since I see a big performance difference (in both editor window open time (Windows or Mac builds) and Mac M1 processing time) simply by switching out the JUCE modules code (doing a clean re-build in both cases of testing each JUCE version).

We have also observed graphics performance issues using 6.1.1. I’m wondering if it’s somehow related to the accessibility changes? We’re reverting back to 6.0.7 for now.

Quick coffee break test as I have to return to the day job… but here’s a couple of screenshots of my own profiler with a launch of the standalone build of my plugin:
Juce 6.07 - editorCreate time is 260ms, with 33ms for instantiation of my editor instance within it.
Juce 6.1.1 - editorCreate time is 1second, 368ms, with 33ms for instantiation of my editor instance within it (ie. same time to instantiate the actual GUI elements)
When running as a VST3 plugin, editor open times are faster in general since the audio processor gets instantiated ahead of time (and any task associated with that are completed already) - especially on 2nd and consequent editor opens (since processor doesn’t get instantiated each time).

(The second line/thread of ticks in the profile view is the audio callback)

6.0.7:

6.1.1:


6.1.1:

FYI… the green lines that appear under the audio thread ticks are my UI oscilloscope function… which only gets called with buffer data once the UI is loaded of course.

(edit: there is nothing conclusive about these traces of course, since I don’t see every thread/process
here - I will need to do a deeper/full trace using the Xcode/VS profilers)

Interesting.
Let us know what you find!

Did you try git-bisect ? Maybe it’s just one very specific change which causes this performance issue.

How are you measuring the time inside the constructor of HyprSynthPluginAudioProcessorEditor? If you’re just logging the time inside the constructor body, you won’t get an accurate result because it won’t include the time taken to initialise the editor’s data members (including those in base classes).

Here, when I build the DSPModulePluginDemo Standalone from develop in a profiler, createEditor is sampled 4 times (it’s quite quick!). Building from 6.0.7, createEditor is sampled 5 times. There doesn’t seem to be any appreciable performance difference in this particular demo.

As the DSPModulePluginDemo editor is similarly fast to open on develop and 6.0.7, I suspect that any slowdown you’re seeing is due to a performance regression in a particular component that is used in your plugin. I recommend measuring in a sampling profiler to find out where the slowdown is coming from. Once you’ve found the cause of the slowdown, we can attempt to verify the issue here, and then hopefully find a solution.

If you have time, running a git bisect would also provide some useful information. However, depending on the size of the “bad” commit this may not be enough information to pinpoint the problem. Therefore, I’d recommend time profiling as a first step.

Thank you for the suggestions and responses.
I don’t have time to dig into this right now, but later in the week I will do some deeper investigation and report back (I admit I don’t even know what git bisect is… so some learning to do too).

Maybe this is of relevance?