Birch-san / juicysfplugin

Audio plugin (e.g. VST, AU) to play soundfonts on macOS, Windows, Linux
GNU General Public License v3.0
227 stars 29 forks source link

[Windows] CPU usage, crash upon scrolling #10

Closed Birch-san closed 5 years ago

Birch-san commented 5 years ago

From https://github.com/Birch-san/juicysfplugin/issues/2#issuecomment-518073892:

Something you may want to know but isn't necessarily much of a problem, (happened 2x) if you leave the plug in up/unattended for 30 mins or more and interact with it right upon waking up the computer, it may crash FL. Maybe Juce or Fluid has some usage timer or something built in? FL?

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.

Birch-san commented 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);
}'
Birch-san commented 5 years ago

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.

Birch-san commented 5 years ago

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.

KJinx101 commented 5 years ago

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.

Birch-san commented 5 years ago

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.

Birch-san commented 5 years ago

is there anything special about your soundfont? I did the stress-test on FatBoy, which has the full 128 presets.

KJinx101 commented 5 years ago

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. Juicy SFP FL debug It only happens when I scroll to the bottom of the patch list and there's the debug ^^

Birch-san commented 5 years ago

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.

KJinx101 commented 5 years ago

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

Birch-san commented 5 years ago

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)
Birch-san commented 5 years ago

Clicking "Retry" puts me on this breakpoint:

image

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++
Birch-san commented 5 years ago

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

KJinx101 commented 5 years ago

Fixed 👍 Thanks!