views:

109

answers:

2

Hi all,

I'm working on a Qt-based MacOS/X audio metering application, which contains audio-metering widgets (potentially a lot of them), each of which is supposed to be updated every 50ms (i.e. at 20Hz).

The program works, but when lots of meters are being updated at once, it uses up lots of CPU time and can bog down (spinny-color-wheel, oh no!).

The strange thing is this: Originally this app would just call update() on the meter widget whenever the meter value changed, and therefore the entire meter-widget would be redrawn every 50ms. However, I thought I'd be clever and compute just the area of the meter that actually needs to be redrawn, and only redraw that portion of the widget (e.g. update(x,y,w,h), where y and h are computed based on the old and new values of the meter). However, when I implemented that, it actually made CPU usage four times higher(!)... even though the app was drawing 50% fewer pixels per second.

Can anyone explain why this optimization actually turns out to be a pessimization? I've posted a trivial example application that demonstrates the effect, here:

http://www.lcscanada.com/jaf/meter_test.zip

When I compile (qmake;make) the above app and run it like this:

$ ./meter.app/Contents/MacOS/meter 72 
Meter:  Using numMeters=72 (partial updates ENABLED)

... top shows the process using ~50% CPU.

When I disable the clever-partial-updates logic, by running it like this:

$ ./meter.app/Contents/MacOS/meter 72 disable_partial_updates
Meter:  Using numMeters=72 (partial updates DISABLED)

... top shows the process using only ~12% CPU. Huh? Shouldn't this case take more CPU, not less?

I tried profiling the app using Shark, but the results didn't mean much to me. FWIW, I'm running Snow Leopard on an 8-core Xeon Mac Pro.

+1  A: 

FWIW top on my Linux box shows ~10-11% without partial updates and 12% using partial updates. I had to request 400 meters to get that CPU usage though.

Perhaps it's just that the overhead of Qt setting up a paint region actually dwarfs your paint time? After all your painting is really simple, it's just two rectangular fills.

Troubadour
Indeed... Under Linux I get very efficient updates with or without the partial-updates optimization. It's just MacOS/X and Windows that don't seem to like it.(In my actual app, it's two rectangular fills and sometimes one or two drawBitmap() calls that are used to superimpose a text label... still fairly trivial though, I think)
Jeremy Friesner
+2  A: 

GPU drawing is a lot faster then letting CPU caclulate the part to redraw (at least for OpenGL this takes in account, I got the Book OpenGL superbible, and it states that OpenGL is build to redraw not, to draw delta as this is potentially a lot more work to do). Even if you use Software Rendering, the libraries are higly optimzed to do their job properly and fast. So Just redrawing is state of art.

penguinpower