Closed Birch-san closed 5 years ago
Will sample juicysfplugin's userland stack-trace with this DTrace script:
sudo dtrace -n '
profile-1001 /execname == "juicysfplugin"/ {
@[ustack(1)] = count();
}
tick-1sec {
printf("%Y \n", walltimestamp);
printa(@);
clear(@);
trunc(@,0);
}'
Ah, I cannot leave DTrace running whilst the computer's asleep. I guess that makes sense. I guess instead I would to leave the computer asleep so long that juicysfplugin hangs, giving me enough time to attach a debugger and start tracing it. Haven't managed to make it hang at all yet.
I'm gonna assume that — rather than sleep, per se — what really matters is suspending the process whilst allowing system time to progress. So, it probably suffices to just pause execution using lldb:
lldb -p `pgrep juicysfplugin`
# note: use `process detach` to resume execution
I froze the process like that, and sampled its activity as I detached the debugger. it didn't have any leap in activity.
I'm so far testing the standalone application only. maybe there's something special about FL Studio. will have to try that next.
Can't attach debugger to FL Studio. Maybe it has hardened runtime enabled? I was able to attach just once (https://github.com/Birch-san/juicysfplugin/issues/8), but then never again.
But I can suspend/resume like so:
kill -STOP `pgrep OsxFL`
kill -CONT `pgrep OsxFL`
I did this, and also tried a real sleep for a few minutes.
Neither technique was able to reproduce on macOS the sleep-wake crash that was reported on Windows.
Windows is not my main system, so I don't have such convenient access to run investigations or develop on it (involves a lot of swapping wires around and burrowing under the desk). Moreover there are gaps in my knowledge of Windows debugging, so it'll be a bit harder to diagnose the problem on that side.
Guess I'll look into this next time it's convenient to do some Windows debugging. If OpenDTrace for Windows has matured sufficiently, then that might help.
Silly me! That wasn't the issue at all. Found the actual bug: If you scroll quickly to the bottom of a list of patches, the CPU usage spikes then it crashes. This is also true for the standalone. I think it was just a matter of me using the plug in more thoroughly upon waking my computer up.
Thanks for narrowing down the repro. that should be far easier to investigate.
I've not been able to reproduce it on macOS standalone. I stress-tested the scrolling in a variety of ways, but I was unable to make the process's CPU usage go any higher than 11% of one core.
will try this out next time I'm on Windows.
is there anything special about your soundfont? I did the stress-test on FatBoy, which has the full 128 presets.
I've tried some GM ones like the musescore general and Musyng kite and well as smaller ones like famicom. Same results. It probably is just a windows thing. I actually was able to see the spike because running the bridged 64 bit plug in in 32 bit FL disconnects the bridge instead of crashing the whole program. It only happens when I scroll to the bottom of the patch list and there's the debug ^^
hm, okay. are those all .sf3 by any chance? that'd account for a couple secs max-CPU on initial load of the soundfont. but admittedly it shouldn't affect scrolling.
thanks for the log output. the Release build of juicysfplugin has all logging disabled, so there's nothing noteworthy there. but that gives us the option of trying the same with a Debug build. simpler to do standalone though, since it sounds like this has nothing to do with FL Studio.
The musescore one might be, but the others are sf2s. I used to rename sf3s to sf2s to use them in fl studio before so I'm not 100% sure. Great that it's something you can do with the standalone
Managed to reproduce it on my Windows machine. Here's the error that's logged when you scroll to the bottom of the list of presets:
Debug Assertion Failed!
Program: ...isualStudio2017\x64\Debug\Standalone Plugin\juicysfplugin.exe
File: c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\vector
Line: 1733
Expression: vector subscript out of range
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
Clicking "Retry" puts me on this breakpoint:
stack looks like this:
> juicysfplugin.exe!std::vector<TableRow,std::allocator<TableRow> >::operator[](const unsigned __int64 _Pos) Line 1733 C++
juicysfplugin.exe!TableComponent::paintCell(juce::Graphics & g, int rowNumber, int columnId, int width, int height, bool __formal) Line 178 C++
juicysfplugin.exe!juce::TableListBox::RowComp::paint(juce::Graphics & g) Line 62 C++
Okay, the fix (https://github.com/Birch-san/juicysfplugin/pull/13) was easy enough.
Here's a new release; tell me whether it works on your end.
https://github.com/Birch-san/juicysfplugin/releases/tag/2.3.3
Fixed 👍 Thanks!
From https://github.com/Birch-san/juicysfplugin/issues/2#issuecomment-518073892:
I assume that we have some tasks that are scheduled to run every n seconds. If the computer is awake, then these will be serviced at a manageable pace.
If the computer is asleep: timed tasks will pile up, and when the computer awakers: juicysfplugin will try to process a massive queue of callbacks.
If this theory is correct: I guess we'll have 100% CPU for a bit. If it happens on the UI thread, then the UI will be unresponsive during this time. If it happens on the audio processing thread: we'll fail to meet our audio processing deadline.
If this is a new problem as of the 2.x releases: my first guess is that this will be related to the slider UI or to the width/height of the GUI. Both of these synchronise their model with the state stored in ValueTree, and I believe that synchronisation is run as a timer task.
I expect this will repro on all operating systems, so plan of action is to attempt a minimal repro on macOS, and sample the process to see where it's spending all of its CPU time.
If the problem is indeed something to do with the new GUI state synchronisation, that will be unfortunate: that code solved difficult problems, so it would be a shame to have to backpedal on it. The obvious solution conceptually is to discard the timer events instead of processing them. This would be a fine solution, but these decisions are made in the bowels of JUCE framework rather than in my own code, so we may lack the access to implement that solution. Upside is that if it is related to GUI state synchronisation, then somebody may have had this issue before: both of those features were written with reference to official examples, so they're probably supported use-cases.