bnilsen.flush();

Posted by Bjørn Erik Nilsen on February 13, 2009 · 13 comments

Hi fellow hackers,

I have found a bug in my brain, it does not emit the readyRead signal properly which means all the public information that was meant to be published at appropriate intervals is not processed. Here follows a manual flush of what I’ve been doing since last time. Talking about everything is too much, so I’ll give you a brief overview.

Last year was pretty much spent on optimizing/re-factoring code related to the Qt Falcon project where the goal was to make Qt 4.5 fly. I mainly focused on painting performance for widgets, i.e. the backing store / window surface infrastructure. After spending a fair amount of time profiling different painting scenarios, I found out the backing store infrastructure was too poor to improve. It simply had to be re-factored in order to make it fly. I finally had an excuse to wear my latex laboratory gloves and white coat in public (I usually only wear this kind of equipment behind closed doors when lobotomizing colleagues). With all the equipment in place–including liters of coffee–the time had come. I was about to replace our platform dependent beast with something new and shiny–preferably cross-platform. After some tough work and patching throughout 2008 I ended up with something useful. Let me remind you that there are no problems, only solutions. I basically removed a lot of QRegion operations and made the update mechanism a whole lot smarter, in addition to many cut-offs for opaque widgets. I will leave out the details and let these numbers speak for themselves:

Qt 4.4 Qt 4.5 Boost (2.0x means twice as fast)
Full update (transparent widgets) 4330 ms 2446 ms 1.8x
Full update (opaque widgets) 3352 ms 1464 ms 2.3x
Scroll (opaque widgets) 50231 ms 3746 ms 13.4x
Partial update (opaque widgets) 4246 ms 1567 ms 2.7x
Complex update (opaque widgets) 4966 ms 2265 ms 2.2x
Full update (opaque children) 3376 ms 1464 ms 2.3x
Move (opaque widgets) 50293 ms 4188 ms 12.0x
Mass update (opaque widgets) 9560 ms 1679 ms 5.7x

Download the sources from here.

With a new and optimized backing store, we were one step closer the goal. While I was working on the new backing store, the other falcon guys were working on a brand new graphics system whose goal was to make it possible to switch the rendering back-end. In order to achieve that, all the painting had to go through our backing store. We had never used the backing store on the Mac before, so my next action point was to put the pieces together and make it happen. Voila, “-graphicssystem raster” on the Mac was no longer just a wet dream. And yes, it was a little bit harder than it sounds.

During all this hacking I also decided to go to DevDays in Munich and Redwood, which implied that I had to prepare two presentations; “Advanced Visualization, Widgets On Graphics View” and “Alien Widgets & Widget Rendering”. I spent quite some time making these presentations the best since sliced bread, and I really hope they were entertaining and interesting. Dev Days 2008 was such a great event and I really enjoyed my stay.

Few days later, back in business here in Oslo with turbo charged batteries, I felt a bit disappointed that I couldn’t show off a graphics view embedded inside graphics view embedded inside another graphics view etc. I knew it wasn’t going to work, so I didn’t even try. However, I made an example having exactly two redirections and that seemed to be more than enough for the hackers in the room, based on the applause it received. This limitation was made on purpose to ease and simplify the shared painter and QWidget::render. However, I was not satisfied with it and thought it would be cool to remove it without adding overhead, so I sat down and did some brain work. And as usual there was a solution to my problem. The shared painter, and hence QWidget::render, now supports an arbitrary number of redirections. Have a look at WolfenQt to see it in action, there’s no limitation of how many times you can “walk into” another graphics view. HTML-5 video in QWebView is another example. Pretty cool.

With that out of my way, I found time to look into a very annoying issue that has followed us since Qt 4.0: “Qt::WA_StaticContents does not work”. Well, it worked for Qt::WA_PaintOnScreen top-levels, but not in general which is really bad since the attribute can have an incredible impact on the performance on resize. It basically means “Dear Qt, do not repaint my entire rect on resize and only repaint newly exposed areas instead”. Just think of it next time you expose yourself for the sun; does it make sense to wear off all the clothes and put on sun lotion on the entire body just because parts of it is exposed? I hope not. I therefore decided to implement the Qt::WA_StaticContents attribute for all widgets in Qt 4.5.0 and here’s the result:

Download the sources from here (run with “QT_FLUSH_PAINT=10″ in debug mode to flush repainted areas with yellow).

I have done several other things too, like fixing lots of bugs, reviewed patches, fixed auto tests, helped out with recruitment, promoted Qt Software at various events and so on. All in all very exciting stuff, and I look forward to new challenges and exciting stuff in the months to come.

OK, that’s it for now. I promise to blog more often in the future, or even write a QQ article (mostly to give back something to Kavindra who has provided me with an unknown number of delicious muffins).

Have a nice weekend and happy hacking!

QShare(this)

Possibly related posts:

  1. Qt + Box2D is easy!
  2. Hi from Bossa Conference (and BossaTetrix)

13 comments

1 Scorp1us February 13, 2009 at 4:06 pm
 

As someone who writes apps that need prefect paint logic/optimization, I thank you.

Everyone else thanks you, they just don’t know it yet. QtCreator splitters really show what a difference this makes! Its smooth and there is little to no flicker. Yum! It really does make all Qt apps sexier!

2 Plikolikop February 13, 2009 at 4:18 pm
 

Great news… Very nice! Thanks for the great hacking!
That’s why i love

3 manyoso February 13, 2009 at 4:22 pm
 

This is awesome blog. I didn’t know you were responsible in large part for -graphicssystem raster! Great work! I really wonder about the 13x improvement on scrolling operations though. That sounds like Qt had some pretty bad code for qwidget scrolling before.

4 Bjørn Erik February 13, 2009 at 4:36 pm
 

@manyoso I’d like to point out that Gunnar, Samuel and Trond did most of the work related to the graphics system itself, I just did the dirty work to get it up-and-running on the Mac :-) Point is: We did it together so we should share the credit :-)

When it comes to QWidget::scroll and its performance improvement in Qt 4.5, most of it is a direct result of having a smarter update mechanism. However, I also added some clever logic to make it faster.

5 Leo S February 13, 2009 at 4:54 pm
 

Awesome work. One thing I’ve always noticed is that rich text edits (text edits with syntax highlighting like you might find in qt creator or kate) repaint pretty badly. Run something like qt creator and then watch the repaints on the text edit as you move the cursor around an opened code file (without editing any text). There are some bad cases when the cursor is near the bottom of the screen it will repaint the whole thing every time the cursor moves. This is actually really noticeable on my original eeepc where painting is dog slow, so it makes editing text quite laggy.

Also seems that QT_FLUSH_PAINT no longer works on recent debian qt builds. Seems like some other define is blocking them. Too bad, I have to use the somewhat cruder “Show Paint” effect in kwin which isn’t as precise.

6 Bjørn Erik February 13, 2009 at 5:09 pm
 

@Leo On which platform do you experience bad text performance? Note that QT_FLUSH_PAINT is enabled only when Qt is compiled in debug mode.

7 Leo S February 13, 2009 at 5:16 pm
 

This was linux. I’m pretty sure I have the qt-dbg libs installed on my machine, but I’ll double check. It used to be I could just run something like QT_FLUSH_PAINT=1 assistant but that no longer works. Couldn’t even get it to work on my own builds in debug mode.. It’s hidden by another define, something like QT_NO_DEBUG_PAINTS or something. (will double check later today).

8 asd February 13, 2009 at 5:29 pm
 

you are THE MAN!
just tried 4.5 on kubuntu with kde 4.2. kmail, akregator used to behave like a slow ajaxapp, now they just rock. well done and thank you very very much!

9 Andreas February 13, 2009 at 6:05 pm
 

Slow painting has been one of the biggest perceived problems in Qt 4 for me. Yes, you *are* the man! Thanks!

10 Boris February 13, 2009 at 6:12 pm
 

Will your DevDays presentation be available somewhere ?
Thanks.

11 Alex B February 13, 2009 at 10:43 pm
 

Erik,

Do users of Qt Embedded using QWS benefit from Falcon project or is it only for Win/X11/Mac ?

Congrats on great results, BTW.

12 Thiago Macieira February 13, 2009 at 11:10 pm
 

The Qt Falcon project was fully cross-platform. It applies to Win/X11/Mac as well as QWS, Windows CE and even S60.

The S60 team has started integrating Qt 4.5 into their branch in preparation for their next release and we’ve got a report from one of thos early builds that the performance improvements are noticeable.

13 Eric Masson February 14, 2009 at 4:28 pm
 

That is great news! I was about to go through a massive Qt Custom Widgets rewrite for the MaXX Desktop and now, voila! Can’t wait to play with it and try different XVisuals+XComposite scenarios like with a ARGB, GL_ARGB and X11_OVERLAY_PLANE. Excellent work and respect from one Eric to another!

Comments on this entry are closed.

Previous post:

Next post: