PDA

View Full Version : QGraphicsView performance



Halabund
16th April 2009, 16:12
Hello,

I'm not a programmer by trade, but I'm hoping to be able to use Qt to display the output of physics simulations in real time (while the simulation is running).

I am trying to learn Qt and QGraphicsView by implementing a flocking (http://en.wikipedia.org/wiki/Flocking_(behavior)) simulation that I already did in Processing (http://processing.org/).

Based on the colliding mice example (http://doc.trolltech.com/4.5/graphicsview-collidingmice.html), I've gotten to the point where I have 100 animated (actually just rotating) triangles ("birds") on screen. The problem is that even without antialiasing, this is much slower than the processing version that has 150 antialiased and semi-transparent triangles of the same size in a bigger window. (I only get 50% CPU usage with Processing, 100% with Qt.)

I believe that the bad performance is due to my using Qt incorrectly (and not Qt being slow). I'd appreciate it very much if you could give me some hints on how to do this properly, or what to do differently. Here's the program (http://dl.getdropbox.com/u/38623/flock1.zip). (I tried to remove everything that was not essential.)

A few specific questions:

1. In Processing, all drawing is done manually, so it very clear when things are being drawn. When is a QGraphicsView redrawn? Does the re-draw happen every time an item is changed in some way (so every time I call rotate() on an item)?

2. I don't understand how timerEvent() works completely ... Is it a good idea that each bird has its own timer, like in the colliding mice example? Would it be better to have a single timer that rotates all of the birds at once? (I actually tried this and it didn't make the program faster.)

3. Is QGraphicsView at all suitable for what I'm trying to do, or is it bound to be slower than Processing? Should I try to use other means of drawing the birds (instead of QGraphicsView)?

I am new to Qt, and my understanding of it is clearly lacking, so please be gentle :)

P.S. I'm on Windows.

wysota
17th April 2009, 09:00
Based on the colliding mice example (http://doc.trolltech.com/4.5/graphicsview-collidingmice.html), I've gotten to the point where I have 100 animated (actually just rotating) triangles ("birds") on screen. The problem is that even without antialiasing, this is much slower than the processing version that has 150 antialiased and semi-transparent triangles of the same size in a bigger window. (I only get 50% CPU usage with Processing, 100% with Qt.)

Get rid of the timer from the bird class and its inheritance from QObject as well. Instead use QGraphicsScene::advance() and QGraphicsItem::advance(). Right now you are updating your view 100 times every frame instead of doing it just once. You should get significant speedup this way. If that not enough, come back here and we'll suggest more optimizations (like enabling cache).



1. In Processing, all drawing is done manually, so it very clear when things are being drawn. When is a QGraphicsView redrawn?
When the viewport is obscured and unobscured, when the scene changes or when the programmer schedules a redraw manually.


Does the re-draw happen every time an item is changed in some way (so every time I call rotate() on an item)?
Yes. The problem is you modify each item separately in a separate timeframe of the animation (as each item runs its own timer).


2. I don't understand how timerEvent() works completely ... Is it a good idea that each bird has its own timer, like in the colliding mice example? Would it be better to have a single timer that rotates all of the birds at once? (I actually tried this and it didn't make the program faster.)
I already answered that, I guess.


3. Is QGraphicsView at all suitable for what I'm trying to do, or is it bound to be slower than Processing? Should I try to use other means of drawing the birds (instead of QGraphicsView)?
I don't know "Processing" but Graphics View is a very fast canvas so there is a good chance it will be at least as fast as Processing once you get a grip on it.


Ok, I rewritten your code and.... it didn't give any improvement. I even reduced the number of items to 4 without any change. Then I started thinking. Qt uses degree based values, so rotating an item around needs currently 360 frames which is 12 seconds with the framerate you set. Try increasing the step of rotation to 10 and your items will magically start rotating 10 times faster. If you want to see what is "slow", increase the number of items to 10000. My optimizations would then start to matter. Setting NoViewportUpdate mode and updating manually and getting rid of separate timers should then help significantly.

Halabund
17th April 2009, 09:07
Thanks for the reply, wysota! I was just writing a followup post when I received it. I'll re-think it in the light of what you wrote, and post it later. It appears that using setViewportUpdateMode with something else than MinimalViewportUpdate makes the program several times faster, but there are still a few things I don't understand about how this works.

wysota
17th April 2009, 10:12
If you have lots of animations you should use either FullViewportUpdate or NoViewportUpdate. And if you don't care about collisions between items (or between items and the cursor), disable indexing as well and set the interactive flag of the view to false, it might all help a bit.