Ivan Čukić

API Design Part 1: Impact on the Performance (Qt vs STL example)

First of all, this post is not meant to criticize Qt in any way, just to raise some thinking points for people who create libraries.

After my talk at aKademy 2014, I’ve decided to start a short series of blog posts about some considerations to be had when designing public API and overall practices to make your code safer and cleaner.

API Design

When we are thinking about the API of a library we are crafting, we usually tend to think only about how easy it will be for the user to use it. And I’d say that Qt is doing very well in that regard.

The problem is that the API design should not be only about that.

When crafting code, we usually ballance between keeping it readable by others, making it execute as fast as you can, to use as less memory as posible etc.

API design should be the same. Although, in this case, you can give a greater priority to the readability, but not by completely sacrificing the other parts.

A small example

A nice example of this sacrifice can be seen when comparing QTextStream::readLine to std::getline.

    // API shortened to look prettier
    QString QTextStream::readLine();
    std::istream& getline(std::istream &input, 
                          std::string &line);

The Qt version looks much nicer – it reads a line, and returns it. It can not be any simpler.

The STL version, on the other hand, returns the (rest of the) stream after the line is read, and it returns the actual line through the out argument. Is there anyone who actually likes the out arguments?

The benefit of this is that you can do a if(std::getline(:::)) and get whether the stream is still valid, which is useful sometimes. But, still, it looks as a harder function to use than the one from QTextStream.

Things start to look a bit different once you start thinking about the most common use case for using a function that returns a line.

    // taken out of the QTextStream documentation
    QTextStream stream(:::);
    QString line;
    do {
        line = stream.readLine();
        // do something
    } while (!line.isNull());

The equivalent code using the function from the STL would be something like this:

    std::ifstream stream(:::);
    std::string line;
    while (std::getline(stream, line)) {
        // do something
    }

After seing the examples, it is a little bit hard to mark the QTextStream::readLine as the clear winner when the ease-of-use is concerned.

Measuring the speed

But, the point of this post is not to talk about that.

The point is to show that the API design has influcence on the other aspects, and not only on readability. The nice API of Qt comes with a significant performance penalty.

I’ve just tested the previous code snippets on a text file that has somewhere around 56000 lines. Each line of the file was longer than 50 characters to exclude the possibility for the libraries to use the short-string optimizations.

The results were measured using the clock() function in the ctime header (start_clock = clock(); ... clock() - start_clock), and the tests were repeated quite a few times:

* Qt code took ~41000 // QString
* Qt code took ~30500 // edit: QByteArray 
* STL code took ~8700

The STL version is almost 5 times faster (edit: 3.5 times compared to QByteArray version).

And it is not because Qt’s implementation is slow or anything. It is mainly because of the API design.

Why is that?

I’ll write the answer below in the comments section to allow you to think about what could be the issue here.

edit: Added QIODevice/QByteArray to the above mix, as suggested by csslayer.

ottens.js

Introducing ottens.js inspired by Kevin’s great talk at aKademy script that does to your web page what should have been done a long time ago. Just call the function when your page has been loaded.

function ottensize() {
    var html = document.body.innerHTML;
    html = html.replace('hacking', 'crafting');
    html = html.replace('hacked', 'crafted');

    document.body.innerHTML = html;
}

… and they pop up on your desktop

If you like to keep your project-related files on your desktop for easy access, you might have kept links to them in different folders which you placed in a folder view.

Now, it is much easier, just link them to the activity they belong to, and set the folder view to display it.

folderview

Linking files to activities

News from the Society for Putting Things on Top of Other Things:

Another feature has returned. This time with less issues and much more speed.

Linking

(yes, activities do need a new icon :) )

Using GNU Global for local source code indexing

If you are not a fan of using an online source code searching tool like lxr.kde.org, but are still tired of grepping for a particular class or function in the KDE Frameworks (and other projects as well), you might find the GNU Global tool quite useful.

It is similar to ctags and cscope, but IMO it works nicer.

You can index your desired project (or everything at once) simply by calling gtags in the project’s root. Later, in order to incrementally update the tags files, you can just call global -u.

global

There are a few options when searching already indexed source tree that I find most useful:

  • no options at all :) – searches for the specified symbol definitions
  • -r – searches for usages of the specified symbol
  • --result grep – apart from listing the contained files, also prints out the line contents.

For other available options, just check out the man page.

Plugins for KAMD and system settings module

All plugins from the old activity manager are ported to the new version.

This means that one of the most requested features is coming back – you will be able to set custom keyboard shortcuts for individual activities as soon as Plasma 5.1 comes out.

Also, the system settings module for configuring activities is back to its full glory (modulo one little visual issue).

kcm_1

Choosing the plugins

Per-activity favourites in Kickoff

I’ve become overly lazy when writing blog posts is concerned. Maybe it is because I’m again working on the user-visible features, and it is much easier to just post a screen-shot or a screen-cast, than to actually write anything meaningful.

Per-Activity Favourites

It also gives the audience a chance to ask ‘does this mean that plasma will have …’ which sometimes brings wonderful ideas to life.

A screencast of the activity switcher in Plasma 5.1

Plasma 5.0 has been released today, but the work does not stop with it.

We have been preparing features planned for 5.1 (and later) for some time now. The new activity switcher is one of them, and it is coming along nicely. It is already much more polished and optimized than the one available in 5.0.

If you want to see it in action, just check out the new screen-cast (I recommend watching it in 720p, it looks much nicer):

Open the video on YouTube >

It shows some old features, but also a few of the new ones.

Be seeing you!

Just a teaser

Activity Window Management

The future of activity switching

I have returned to the colourful world of UI (still refusing to say UX :) ) development.

The new pretty thing that is taking away my time is the activity switcher which got a rather big revamp for the next release of Plasma.

Activity Switching in Plasma After Next

Apart from the new UI, it got a few usability improvements, namely full keyboard navigation. You are able to filter, navigate and switch activities without touching your mouse.

Meta+Tab activity switching

Unfortunately, not all is great – the Meta+Tab shortcuts for switching activities are not going to be enabled for the first release, they will have to wait for the one after.

What will that look like?

As you can see in the screen-cast, the Meta+Tab will (unlike old Plasma) have a visual feedback – it will show the switcher until you release the Meta key. Similarly to how Alt+Tab for window switching works.

Per activity global shortcuts

The second thing that will need to wait is the port of the global shortcuts plugin by Makis Marimpis. I expect it to be present in the same release as Meta+Tab.