Sunday, September 19, 2010

Qt Creator: Improving user experience

I use Qt Creator daily (to be more specific - one of the latest builds).
Every week it becomes better, bug fixing and feature improvements are ongoing.
Qt Creator (and Qt) is Open Source and almost anybody can contribute it. It is available on Gitorious.

What is the most annoying in Qt Creator now? For me it is the time I have to wait before Qt Creator will be loaded and ready to work. On the clean PC with just cached previously started application - it takes about 800 ms only, but otherwise - it can take 5-10 seconds, and some time - up to 30 seconds (I use Ubuntu 10.04 x64 with T7500 CPU and 3 GB RAM). Can it be somehow improved? I decided to check this issue.

Qt Creator consist of different plugins (a lot, the list + description is available in Help - About plugins). Source for the plugin library is here: src/libs/extensionsystem. It is possible to profile plugin loading by using an option '-profile'. After loading - every plugin is initialized by initialize (initializePlugin in the report) and extensionInitialized (initializeExtensions) calls. Difference is the order of dependent plugins' execution, it is easy to see by the '-profile' output.

So what is the real result for Qt Creator loading? What is the slowest plugin?
    TOP5 plugins by loading time
  1. Welcome - suddenly it can take up to 20-30% of full Qt Creator loading time.
  2. Core - this is really a core for Qt Creator, so it is hard to optimize it.
  3. Debugger - also a lot of features / sub-plugins.
  4. Find - quite interesting why it is here
  5. Qt4ProjectManager
Why it is TOP5? It had to be TOP3, but there is a Core plugin, and it is very complicate. :)

Find plugin - short investigation shows that it is due to X11 specific problem, QApplication::clipboard() has to initialize X11 desktop also. So it is X11 problem only, can be investigated more later.

Ok, lets try to check Welcome plugin. Most time is consumed by WelcomePlugin::initialize. Sources can be find here: src/plugins/welcome. What is going on there? Lets profile it more carefully.
Most work is done here:
m_welcomeMode = new WelcomeMode;
So what is the WelcomeMode::WelcomeMode()?

Additional profiling - and the next 2 lines require most time for the execution:
m_d->m_welcomePage = new ImageWidget(QPixmap(":/welcome/images/welcomebg.png"), m_d->m_widget);
2nd line is just an usual UI setting up (from Designer), it is executed quite long time but it is hard to investigate why (is it related to Qt - to styleSheet usage?..) So lets try to check 1st line - what is exactly done there and why it is so slow? ImageWidget::ImageWidget() is almost empty, so the longest time is required for QPixmap creation. ImageWidget does not use this QPixmap directly anyway, and uses it for the scaling source only.

What is src/plugins/welcome/images/welcomebg.png? Some info:
21649 bytes, PNG image, 800 x 600, 8-bit/color RGBA, non-interlaced

So it is quite a big image (~2 mb unpacked). What might be the problem with the performance? Try to check Qt documentation: "QImage is designed and optimized for I/O, and for direct pixel access and manipulation, while QPixmap is designed and optimized for showing images on screen." As mentioned already, ImageViewer uses the source image (m_bg) for the scaling source only, how the scaling is implemented? Check Qt sources, QPixmap for the scaling uses QPixmapData::transformed. It is implemented so:
QPixmap::fromImage(toImage().transformed(matrix, mode));
So lets try to change QPixmap as a source for the background in ImageWidget to QImage (it will be faster even for the scaling). It will be so:
m_d->m_welcomePage = new ImageWidget(QImage(":/welcome/images/welcomebg.png"), m_d->m_widget);
And ImageWidget has to be changed accordingly.
Patch is available here.

Ok, lets test will it be really faster or not.

Welcome plugin does not depend to any other plugin except Core, so to do the testing more real - Qt Creator will be compiled in the release mode for the next Qt 4.7 version: 4.7.0~rc1+git20100917-0ubuntu1.
    How the testing will be done?
  1. Start old Qt Creator, wait until it will be ready, kill it, wait 5 seconds
  2. Start new Qt Creator, wait until it will be ready, kill it, wait 5 seconds
  3. Go to 1
Test results (time in ms):
initializeextInittotal loadinitializeextInittotal load
both139 both416
Together: 139 ms (81 + 58) for modified Qt Creator vs 416 (352+64) for original one. Reduced to about 33%, or +200% to the loading speed for particular Welcome plugin. Full load time - about 300 ms faster or +33%. 900 ms vs 1200 ms - it is palpably faster.

Is it really so? Yes and no.
  • Yes, at least for X11 Welcome plugin became faster per 200% (on the particular PC). And for any platform - in ImageWidget::paintEvent due to the scaling.
  • No, the test is synthetic. There is enough available memory, and a lot of files might be cached, so even 2 different Qt Creators start faster than usual. E.g. here Qt Creator starts in 25 seconds: QTCREATORBUG-2396. 250 ms (or even 5 seconds) faster for 25 seconds - it is almost invisible.
A test on the much faster PC (the same Ubuntu 10.04, T9600 @ 2.80GHz + 4 GB RAM, Video: Quadro FX 770M) does not show any speed up at all. So this is even a more specific patch, related to something else (some resource?...)

For the created patch - a merge request is created. Lets hope it will be accepted. :)

WelcomePlugin::extensionsInitialized (and other plugins) will be investigated and considered later.

Conclusion: Qt Creator's loading speed might be significantly improved.

It just has to be done, and of course to be done correctly. And there are a lot of other, more important tasks for Qt Creator team. What is one of the main difference between official Qt Creator team and any independent developer? Priorities. An independent developer can spend a lot of hours for some minor suggestion due to any reason, for example, because it is interesting.

Except improvements for the current solution, any other possibilities might be considered, e.g. boost showing the main window with base plugins only - and continue the loading in the background (e.g. Settings widgets) etc.

Ok, what is the main reason for this article? To show that anybody can help Qt Creator to become better. Also I am looking for a new challenge, and I decided to try to speed up Qt Creator loading. Do you want to participate?..

Any feedback is highly appreciated.