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…
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.
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.
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).
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)
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).
Wow, I can’t believe two weeks have gone by already - sorry that I’ve been snowed under with personal and work stuff - no time to dig into this.
I can say that I am not using a tree-view, and whilst I do have a node tree system with potentially lots of child GUI components, it only gets instantiated/built when the plugin process instance is created, and not when the UI window is created/closed/re-opened - however since the elements are made visible/resized when the editor window is created, maybe that’s related to the delays seen.
I’ve been having this issue as well lately, to the point that even optimized release compiled builds would cause interrupts whenever the editor was opened and closed.
I did a high-accuracy performance profiling on the construction of my editor without running any of the audio related systems for improved accuracy.
I found that a lot of the issues for me were caused by the fact that I have a custom slider / textbox / label composite component that called functions in each of their constructors that involved doing sendLookAndFeelChange() callbacks; Things like setColour(), setSliderStyle(), and setLookAndFeel() took up an overwhelming majority of the CPU utilized during construction.
Looking deeper, I found that I’m calling createSystemTypefaceFor() repeatedly when I’m creating these composite components (two times for each knob, and a LOT of knobs) so that would be the fix for me.
I’d probably suggest a more scrutinous look towards the look and feel / typeface related systems within your components (and if you’re loading in components which are not initially visible remember to use addChildComponent() instead of addAndMakeVisible()) for a performance boost.
Thanks for adding your comment to this topic - I’ve just been so wrapped up in building out releases on JUCE 6.0.7 I didn’t get back to investigating this yet.
I do have a lot of custom look and feel stuff, mostly just called one time using setDefaultLookAndFeel in the editor constructor, and also did use defaultTypeface = Typeface::createSystemTypefaceFor = .... in that LookAndFeel_V4 object’s constructor.
Still strange that the initialization behavior would be so different between JUCE versions - I will certainly take a closer look as I now have a couple of weeks without any planned feature/bug fix updates to my plugin.
I found my plugin suddenly started taking >5 seconds to instantiate the editor. Turns out it was because I was adding a bunch of help text to a TextEditor during construction. Interestingly, setting the text on demand is quite quick…
Sorry for lack of updates on my side, I really just didn’t get time to investigate this until now - life happens… time flies.
Updating from 6.0.7 to 6.1.4 - editor opening time seemed a bit quicker vs 6.1.1, but that might have been due to some code changes I made in terms of initialisation sequences, however, there was still a significant delay in opening the plugin editor (especially on Mac).
I don’t know for sure why the time for opening the editor was significantly worse after upgrade from 6.07 to 6.1.x but after some profiling I found that it may partially have been related to some text editor initialisations/reading text from a file (which I now moved to happen only at the point that particular text is required), and the lowest level ‘pin’ component of my node tree having a setLookAndFeel (which I removed by putting the necessary change into my global overrides/default look and feel) - saving a fraction of a second (still this doesn’t explain why these things take longer after moving to 6.1.x).
However, even after these tweaks the Mac build was still taking 2-3 seconds to open the plugin editor when built on 6.1.4 (comparing to 6.0.7 on same Mac/OS version) - even though exact same Windows source code build did not show that delay.
I tracked this down to my patch list/file scanning code which launches a DirectoryContentsList thread - two issues:
The isFileSuitable filter was opening the text files to check for suitability instead of just only checking the file extensions.
Edit: the Directory contents list thread-priority is less significant than I thought after a retest, but still I think has an impact:
Secondly, at least on the Mac build, the default thread priority of DirectoryContentsList thread seems too high… dropping it by calling setPriority(3) made a difference.
So, for me the biggest factor was DirectoryContentsList…(combination of reading files and thread priority) and it seems there’s a difference with Windows vs Mac here, and the priority would appear to be the same as the UI thread by default? (which is not what I want for a background folder scan)
Is it possible that DirectoryContentsList gets a lower priority by default in prior versions of JUCE?
I guess it depends on the DAW/host, but the plugin processor is usually being initialised for the first time when you first add the plugin and if the plugin window is opened automatically - any statically allocated objects you have/wavetable initialisations, restore state, prepare to play etc. happen before the editor is created - so it’s normal for opening time to take longer the first time.
However if the length of time for that is significantly longer since upgrading to 6.1.4 then I’d suggest you do what I did and profile the code more deeply with Xcode/Visual studio profilers and look at what consumes the most time in the startup sequence.
After profiling I found that text initialisations of TextEditor components can take a lot of time - not sure if that is a new issue or was always the case, but I didn’t dig much deeper than moving the worst one out of the plugin editor constructor (reading in a multi-line string from binary data) - and now making it happen only when the component visibility was changed.
In your case it sounds like it’s not your UI/editor initialisation that is the cause of the delay. Maybe also have a look at any breaking changes in the release notes of 6.1.x vs older releases.
For my case, I don’t really know the underlying architecture of how JUCE requests threads/priorities from the OS and didn’t try to dig deeper, but I’m just making an educated guess that something changed for Mac builds between 6.0.7 and 6.1.1 which meant I needed to force a priority drop on the Directory contents list timeslice thread to avoid slowing down UI intialisation (and the reason it was so noticeable was because I was opening every text file in my filter function - if I didn’t do that, the difference is not so much).
I also just updated to juce 6.1.6 from version 6.0.7 and have noticed a serious decrease in performance when instantiating text editors (or using setText). It appears the slowness is most prominent for editors set to setMultiLine(true, true), which makes sense. The app I am working on uses many text editors by necessity, and previously it was working great/fast with the older version of juce 6. On my machine, it takes about 50ms to setText() on an editor with multiline enabled, which is very noticeable when you are setting 5-10 editors. I’m not sure what the best way around this is.