JUCE146 vs. JUCE152 drawing speed


#1

I’ve made a multipoint envelope for a customer, and it runs very smoothly on JUCE146 with about 20% CPU usage. I’ve even added some scrolling some exponential decay, so it looks like the scrolling on some iPhone.
Now I’ve ported this Component to JUCE152, it eats all CPU and just stutters very badly. The CPU usage of one core is 100% as soon as I start scrolling.
The functions I use for drawing are mostly: Graphics::fillAll(), Graphics::fillRect(), Graphics::drawLine(), Graphics::drawVerticalLine(), Graphics::drawHorizontalLine().

I’d say it runs about at least 4x less faster than the original.

Why is JUCE152 so slow when JUCE146 did its job very well?


#2

What platform?


#3

Forgot to say that the environment is just the same for both .exe’s . It’s a ASUS with Intel dual core on Win XP. Both .exe’s compiled in Release mode.


#4

1.46 had much more limited graphics abilities than the newer releases - I rewrote the entire graphics stack since then. I’m surprised that you’d see such a big difference though, I’ve found it all to run extremely well, and some operations will certainly be quicker than before - I guess you might just be relying on a couple of operations that are slower. If you can profile it and point out the hotspots, I can take a look and see if there’s anything that can be done.


#5

I seem to have boiled down the causes:

Graphics::drawVerticalLine() & Graphics::drawEllipse() : slower than in JUCE146
Graphics::drawLine() : unbelievably (!) much slower than in JUCE146

Although it seems that the rendering looks nicer in JUCE152, it also is alltogether unusably slow.

(Jules, ) I’m open for suggestions on how to fix the problem.


#6

Weirdly enough, when I run the same .exe from the Explorer, it’s much faster (actually very useable, but still 2x slower than with JUCE146).


#7

Ah, that’ll be MSVC’s debug memory allocator. I think TheVinn will have a thing or two to say about that!


#8

Ok, but still it’s 200% slower than JUCE146 (although the rendering looks more clean, I agree). What do you have to say about that?


#9

Same thing I said in my first post.


#10

Damnit! You beat me to it again! Yes, when the debugger is attached to a compiled .EXE, even if you run a Release build (i.e. full optimizations) the debugger installs hooks into your program. It intercepts housekeeping events like thread creation / destruction, exceptions, DLL loading / unloading, and slows those calls down. But also, it instructs Windows to launch the application with a “checked heap” facility. Note that this is built into Windows and something separate from the “debug heap” (which is provided by the runtime).

The bottom line is that applications running with the MSVC debugger attached will perform more poorly.


#11

Same thing I said in my first post.[/quote]

Sorry I didn’t see that post. Well I think I’ll try not to use drawEllipse() for a start and get back to you if I do some findings.
I could also be that due some modified Timer code, there’s a difference? (I am using a Timer of 100Hz with Timer::startTimer(10), so the Timer speed is quite high, and maybe this works at a higher rate than in the old JUCE versions)


#12

Damnit! You beat me to it again! Yes, when the debugger is attached to a compiled .EXE, even if you run a Release build (i.e. full optimizations) the debugger installs hooks into your program. It intercepts housekeeping events like thread creation / destruction, exceptions, DLL loading / unloading, and slows those calls down. But also, it instructs Windows to launch the application with a “checked heap” facility. Note that this is built into Windows and something separate from the “debug heap” (which is provided by the runtime).

The bottom line is that applications running with the MSVC debugger attached will perform more poorly.[/quote]

Ok, can I turn this nonsense off? I just want to work like in my beloved VS2003.


#13

Add “_NO_DEBUG_HEAP=1” to Project Properties->Configuration Properties->Debugging->Environment for the Release target to disable the checked heap.

Unfortunately there is nothing you can do about exception / thread hooking, other than just running without the debugger (i.e. CTRL+F5).

What I do in my app, is avoid exceptions, and re-use threads (when I am finished with a thread I save it in a pool and re-use it later so I dont have to ask the operating system for a new one).


#14

There are some issues that happens only in XP systems that could explain some zamrate problems:

  • Popups and drag images (maybe more things) results in 100% cpu usage. It can be adressed via “typedef SpinLock LockType;” inside juce_Timer.cpp class. It looks like that it’s related to the spinlock class. More info here.

  • When closing VST plugins there is also 100% cpu usage (…like said only XP) during some time, it’s like something gets locked more than usual, this issue is also very recent (it appeared at the same time than the above one, but I don’t know yet the cause).


#15

I’ve tested on my old XP machine and can’t reproduce it… and I can’t see any reason why a spinlock would cause a problem in the timer - it’s only held for a very short amount of time. Are you saying that by changing that SpinLock typedef to a CriticalSection these problems go away?


#16

Yes (…sorry, I didn’t explaing it very well the first time) . When you change the Spinlock by a CriticalSection the problem go away. For more info, I’m using XP sp2 here .


#17

Very odd. I don’t think it can be XP that makes the difference, because it certainly doesn’t happen on all XP machines, but I really don’t understand why that’d sometimes cause problems.


#18

it seems that there are many xp-related (and hardware-specific) issues, (maybe it has to do with the thread-scheduler on single-core machines, just an assumption) with the Spin-Lock, maybe its just better to return to the good old CriticalSection, if it has in no disadvantages in practice.

http://www.rawmaterialsoftware.com/viewtopic.php?f=3&t=7161
http://www.rawmaterialsoftware.com/viewtopic.php?f=8&t=7116


#19

or maybe compareAndset is very slow on some CPUs (because all threads have to stop)


#20

Did we actually test the performance of the SpinLock ?

I avoid spin locks in my own code whenever possible. The only time I use a spin lock is when I want a mutex-type synchronization primitive that does not require a constructor (since spin-locks can be initialized by zero-fill when the executable image is loaded).