Motor Tuning

Mittlerweile hat das KDE Release Team begonnen die Quellcode-Pakete für die KDE Applications, KDE Workspaces and KDE Platform in Version 4.9 vorzubereiten, was für mich mal wieder ein guter Zeitpunkt ist zurückzuschauen auf das letzte halbe Entwicklungsjahr im KDE Plasma Fenstermanager und Compositor KWin.

Für den Nutzer wird es in KWin 4.9 nicht viel Neues zu sehen geben. An einigen Stellen haben wir die Benutzbarkeit etwas erhöht, so zum Beispield das Konfigurationsmodul für Fensterwechseln komplett überarbeitet und das Konfigurationsmodul für Fensterdekorationen ist nun interaktiver geworden.

Dies war aber auch nur möglich durch einige Arbeiten unter der Haube. Die Fensterdekorationsengine Aurorae wurde mittels QtQuick neugeschrieben, ist dadurch bedeutend wartbarer und performanter geworden und ist nun zumindest auf meinen Systemen performanter als unsere Standarddekoration Oxygen. Als Nebeneffekt kann der Quellcode auch in dem Konfigurationsmodul verwendet werden, was die nun existierende Interaktion erst ermöglicht.

Aber nicht nur der Motor der Aurorae Themes wurde getuned, nein der ganze Fenstermanager musste an sich Anpassungen ergehen lassen. Der Startvorgang ist deutlich beschleunigt, vieles wird nun parallel abgearbeitet und generell wird nicht mehr so viel gewartet um zum Beispiel eine Konfigurationsdatei einzulesen. Das dürfte je nach Hardware den Startvorgang des KDE Plasma Desktops um ein paar hundert Millisekunden beschleunigen.

Durch die generellen Umbaumassnahmen am Motor waren wir auch in der Lage einige richtig alten Bugs zu beheben. So ist der zweite Bug Report, den ich für KWin als Entwickler aufgemacht habe, nun endlich behoben: Fenster werden nach dem Schließen nicht mehr über andere Fenster gesetzt sondern behalten ihre Position. Was eigentlich nur nach einem Schönheitsfehler klingt, ist durchaus auch relevant für die Sicherheit. Durch diesen Bug wurden Benachrichtigungen für ein paar Millisekunden über der Bildschirmsperre angezeigt. Leider ist die Änderung doch sehr tiefgreifend und bringt den Motor noch etwas zum “stottern”, daher können wir die Änderung nicht in 4.8 einarbeiten. Bis zur Veröffentlichung von 4.9 bekommen wir das Stottern aber noch in den Griff. Gerade eben hatte ich einen Crash dadurch, fünf Minuten später war der Review Request mit dem Fix bereits erstellt.

Auch in anderen Bereichen haben wir daran gearbeitet, dass der Motor einfach runder läuft. So wurden die “Fenstertabs”, also die Funktionalität mehrere Fenster in einer Fensterdekoration zu haben, komplett neu geschrieben um die Stabilität zu erhöhen. Dies war ursprünglich einmal ein Google Summer of Code Projekt gewesen und wurde leider nach Abschluss des Projekts vom Studenten nicht weitergepflegt.

Auch ein anderes Google Summer of Code Projekt wurde in diesem Release Zyklus neu geschrieben und ausgebaut: Scripting. In 4.9 können nun Skripte entweder als JavaScript oder als QtQuick geschrieben werden und wir machen davon durchaus Gebrauch. Die Anzeige, wenn der Desktop gewechselt wird, wurde durch ein QtQuick Skript ersetzt und einige Anpassungen zum Deaktivieren der Multi-Monitor-Unterstützung haben wir in Skripte ausgelagert.

Skripte können nun auch bedeutend einfacher erstellt werden, nämlich über die Window Skripting Console, zu starten über KRunner (Alt+F2) und dann “wm console”. Der JavaScript Code wird direkt im Fenstermanager ausgeführt und ermöglicht somit ein sehr einfaches Ausprobieren der Skripte.

Ein zusätzliches Highlight ist, dass man nun Desktop Effekte in JavaScript implementieren kann. Ein paar Effekte haben wir damit auch bereits ersetzt und einige hundert Zeilen C++ Code durch ein paar JavaScript Zeilen ausgetauscht. Interessant ist, dass dies keinerlei Auswirkung auf die Performance hat, denn zum eigentlichen Zeichnen und Animieren wird weiterhin ein ausgereiftes C++ Backend verwendet. Ausschließlich Code zum Starten der Animation ist in JavaScript geschrieben.

Zusammengefasst denke ich, dass unsere Nutzer sehr zufrieden mit diesem Release sein werden und uns nachsehen werden, dass es keine neuen Spielereien gibt. Dafür haben wir aber die Grundlagen gelegt, dass unsere Nutzer selbst mittels JavaScript und QtQuick neue Spielereien nachreichen können. Mein Vortrag auf der diesjährigen Akademy wird sich um genau dieses Thema drehen.

Wer die Entwicklungen der KDE Community finanziell unterstützen will, kann zum Beispiel bei Join the Game teilnehmen. Für die KDE Community ist solch eine Unterstützung unglaublich wichtig, da wir Server zu bezahlen haben und wir das Geld einsetzen können um Entwickler zu den Sprints zu fliegen. Gerade die Entwicklersprints sind unglaublich hilfreich für die Entwicklung der Software, da hier die Entwickler die Möglichkeit haben mal direkt miteinander zu sprechen als immer nur über E-Mail oder IRC.

BKO: Bug dependencies

This is the sixth blog post in my series bugs.kde.org for developers.

During software development it is quite normal that you have some dependencies between the bugs and features you want to implement. E.g. for feature foo you first have to implement feature bar. Bugzilla can help you track such dependencies in a nice way.

In most KDE projects I have seen poor man solutions to manage these problems. The most obvious one is to just write in one of the comments that first the other bug report needs to be implemented. But that’s a very bad solution. It can only be processed by humans by reading the comments and from bug report bar the reference is missing completely.

Another solution is to set bug foo to resolved later indicating that at some later state the bug will be fixed. But how likely is it that you remember to reopen that bug after you have implemented foo? I think it’s rather unlikely given the amount of bugs reported on bko that anyone is considering the resolved later bugs. I just checked that for KWin and of the 17 bugs resolved later many are fixed right now.

Another solution I have seen is to create a meta bug and set all depending bugs as duplicates of this one. We then find comments like “note: please check duplicates”. This is also a very bad solution as it requires to read through all the bug reports and it’s not what duplicates are for. It’s not the same issue after all.

All these solutions have one clear drawback: they cannot manage dependencies hierarchies. Consider the following hypothetical feature request: a user wants to be able to interact with a rotated window. This requires first generic support for rotated windows and support for input redirection. Input redirection makes only sense with Wayland. For this we need to add at least a build dependency in CMake, implement Wayland server and get rid of X. If we would want to we could split this up even further and we have a nice dependency tree like this one:
Bug Dependency Graph

This is a graph rendered by bugzilla. So how does it work? It’s quite simple. Each bug report has two fields to manipulate the bug dependency: “Depends On” and “Blocks”. A bug which depends on another one can only be set to fixed after the other one is fixed. The same way a bug which is blocked cannot be fixed as long as the bug which is blocking is not fixed. In fact these two are exactly the same: if you add a depends on, the other bugs blocks field will be updated. So you can always navigate the tree from both sides.

Using the bug dependencies can really help you if you split up your work into multiple tasks. Combined with the searches you can get bugzilla telling you which bug you have to work on.

Profiling of KWin

In my last blog of KWin I described the improvements in the startup of KWin. Since then I did some further profiling and could improve a few effects to load resources only when needed. E.g. Present Windows effect created the texture for the window filter on startup. This is now delayed till the user starts to type which means not only about 20 msec faster startup but also less used resources in case the user does not use the filter at all. The effect (and other effects) had created this texture on creation since 4.3. Of course it’s not a long waiting time, but in multiple effects which need to be loaded at startup it sums up to a noticeable delay.

My investigations have now reached a point where I think there is hardly anything left to do for 4.9. We still have some I/O when starting up the OpenGL compositor (150 msec) as we need to load the shaders from file but this will be quite difficult to improve without a major rewrite on how the compositor startup works, which is of course not possible for 4.9 any more and I want to change the compositor startup anyway for 4.10.

Also remaining is currently the X communication in the startup. There are many round trips to the X Server and that can unfortunately be noticed. It’s something which will hopefully improve in 4.10 by making stronger use of xcb.

Given that I was doing profiling I was also interested in our rendering and had another look at this to see why we sometimes are not able to render at 60 frames per second. My results are very promising. Some of the assumptions which we already had could be validated which means I have a general idea where I need to optimize. It will be interesting work as for that I won’t have to touch KWin source code. And I find it quite satisfying that we have reached a point in KWin development where we need to optimize non KWin code to improve the performance further.

What remains is how I did the profiling. The obvious candidate would be callgrind, but it is not really useful to find delays in the startup. In case of KWin the compositor is dominating the results of callgrind so that the calls which are executed just once are hardly visible. Another problem with callgrind is that it does not show us when we are waiting for I/O or X.

I needed to know how long the actual tasks take to perform. Therefore I needed to add profiling information which ended up in this small class:

class Timing
{
public:
    Timing(const char *message)
        : m_message(message) {
            m_timer.start();
        }
    ~Timing() {
        std::cout << m_message.latin1() << ": " <<
m_timer.elapsed() << " msec" << std::endl;
    }
private:
    QElapsedTimer m_timer;
    QLatin1String m_message;
};

With that I spiced up my KWin checkout to contain many Timing timing(“Load Cube Effect”); statements. And it allowed me to get very close to where the time is spent.

Overall I take from this experience that the key to a faster startup is not a more parallel startup through things like system-d, but that actually you have to question everything you do. Of course it is useful to construct everything an object needs when the object is created, but it might not be what is actually required. This is quite the case for plugins and especially 3rd party plugins. I would be positively surprised if a third party author of a Plasmoid is aware that loading an image in the Plugin ctor will delay the startup of the complete KDE Plasma session.

So if someone wants to work on getting the startup faster: there are many Plasmoids and I am sure for quite a lot we can put loading of data into threads and delay calls into the next event loop. Also it could be nice to create some krazy checks to test for common “mistakes” like loading an image not in a thread.