Monday, February 08, 2010

krunner responsiveness

The RunnerManager interface in libplasma which powers KRunner (among other interfaces) was designed to allow plugins a-plenty so that one search term could be matched in "real time" by several different components, each one looking for answers in different ways or places. This isn't a particularly unique design by any means, and the concept can be seen in many search interfaces out there.

A "run command" app faces a challenge with this sort of design: in usage, one expects the interface to appear "instantly" when called up and remain responsive during use. This isn't the web where pages can take significant fractions of a second without anyone caring or where we can stack dozens/hundreds/thousands of servers behind your queries to offer mindcrushing amounts of compute power to chew through whatever gets thrown at it. No, we have to be fast with limited resources while looking in all kinds of places. Basically, KRunner has to be as responsive as the KDE 3 minicli while doing orders of magnitude more processing. Interesting problem.

To address the problem we made the query plugins, or "runners", multi-threaded even when we only had 2 of them. This ended up involving lots of queue management, but Threadweaver made that as easy as possible. We got rid of many locks as development went on, improving interactivity, and eventually ended up introducing the concept of a query "session". In KRunner, a session starts when the user interface is shown and ends when it is hidden. Runners are given the opportunity to set what they need during searching up at that point. Later, when the session is over, they can tear down all of that allowing us to conserve resources and not wake up KRunner every time a window twitches. This also helped speed up querying in some cases as it meant moving initialization routines that were being run in some cases on every keystroke to once-per-session.

The prep and teardown for sessions is not multithreaded, however. Or rather, the signals that a session is about to begin and end are not. This gives runners some comforting guarantees as to their ability to manipulate pixmaps or x.org information (things that can not be safely done from outside the main application thread) as well as to the order of events: prep, querying, teardown is a guaranteed order.

The new issue that query sessions brought was that some runners have grown time consuming code that is run during session preparation. There were a handful of runners that were taking 20-80 milliseconds each every time the user interface was to be shown. That may not seem like much, but it quickly added up to over 150ms on my dual core 2Ghz laptop which is very noticeable to the human eye. Since this code was running in the main application thread, popping up the KRunner window felt really slow. The question was: which runners were responsible for this and why? Some profiling was in order!

So I popped a small three-line patch into libplasma that measured how long each runner was taking during session preparation. The problem plugins were immediately highlighted. So I went through each of those and did some profiling to see where they were spending their time and pushed code around until the prep time was more reasonable. Most of the work was taking synchronous operations and making them asynchronous. At this point, none of the runners on my system take more than 1-2 milliseconds to prep, which means instead of waiting 0.15 seconds for something to happen after I press Alt+F2, it appears almost immediately. The difference is very noticeable and very pleasing.

What's interesting is that, with one exception, none of the runners are doing any less processing. In fact, in a couple cases they are doing a little more (though nothing to write home about), but the result is something that feels much smoother and more pleasant to use.

I backported the results after testing to the KDE SC 4.4 branch. I don't think the improvements will make it into 4.4.0 (it's already tagged and being packaged) but should be in the 4.4.1 release at the latest. So if you have been finding KRunner sluggish to appear and build from sources, try updating kdebase/workspace/plasma/generic/runners/ and kdeplasma-addons/runners/ and see if things improve after a restart of KRunner.

14 comments:

Blackpaw said...

Nice, I had noticed a slowdown in Krunner appearing. Look fwd to 4.41

Daniel André said...

To be honest, I find the results appearing "as I type" to be lot more sluggish. Could be a kubuntu thing or whatnot, but it definately does not feel smooth when trying to find as I type in krunner.

Can't remember it was that slow in 4.3, but I have no data to prove that.

Mark said...

Thanks that sounds really great. I had already disabled a few runners, because of the slow responses. Now if krunner could force itself to stay on top of all other windows that would be really great.

Aaron J. Seigo said...

@mark: the "on top of the screen" mode, which is the default in 4.4, does that.

Danni Coy said...

I am generally having a problem with krunner where it is taking 15-30% cpu on my atom netbook while running in the background. I have disabled all the runners except the application runner.

https://bugs.kde.org/show_bug.cgi?id=225598

megabigbug said...

I tried to develop a runner able to query websites that folow the specification opensearch (http://www.opensearch.org/Home)

I use kio for the query. It is very slow and krunner doesn't like that but I get some results.

If someone is interested I can share the code.

I dream of an internet integrated in my desktop.

Aaron, can you tell me if you plan improvements in KRunner to achieve this goal ?

Aaron J. Seigo said...

@Danni Coy: i've replied on the bug report. let's see what we can do.

@megabigbug: "It is very slow and krunner doesn't like that but I get some results."

what problem are you having with krunner? the amount of time it takes for a runner to return with matches shouldn't matter, though what krunner -will- do is de-prioritize slow runners so that they don't take over the thread pool.

if you are blocking inside your match() method, that's probably the source of your pain. if you make match() asynchronous, easy since you are using KIO, then you can return quickly and cancel KIO jobs that become stale (due to the query changing).

some runners actually introduce a small delay before fetching results to prevent unnecessary lookups; that means that there is a pause after typing but in those cases that's bound to happen anyways.

in any case, sharing your code would be great. kde-apps.org is great for that, and you can always ask questions about these kinds of issues on plasma-devel@kde.org

abrouwers said...

Any chance you can post a link to your patch? I'd really like to try it out on my new 4.4 install, but trying to navigate through websvn is reeeeally slow just after the release :)

Andrew said...

Awesome work.

Aaron J. Seigo said...

@abrouwers: it was actually a series of patches to the windows, bookmarks, kill and kopete runners. you may as well just grab the runners wholesale from the 4.4 branch or trunk due to that.

Mal said...

Couldn't find the best place to ask this, so I'll try here.

I'd love to be able to replace the kickoff menu with a static krunner 'omnibox' (well, that's how I think of it). I mean, I know what my apps are called - why would I want to navigate some arbitrary folder structure to find it?

Is there a way that would be possible?

Aaron J. Seigo said...

@Mal: in 4.4, kickoff's search box is powered by Runners just as krunner is.

i do expect someone to eventually get around to a krunner like plasmoid you can place anywhere, though i think the krunner window itself tends to fill most of the needs/desire and thus motivation to do such a thing.

jhg said...

This is really really great news !!!
IMHO response time is one of the most important issues of KDE 4.x. (more important than any new feature).
I´m still using KDE 3.x at work, because I need a desktop, which is doing "what I want" and "without any secound of thinking".
With this fix for krunner I will definatly try KDE 4.4.1.
Thanks ... !!!! Keep on with this kind of work !!
Do you think it is possible to somehow check the whole KDE source automatically for possible performance-problems?

Andras said...

Great news. Right now with 4.4 I have big problems with KRunner on two different computers (and one is quad core, 8GB ). Actually there are two issues (sometimes just hags for several seconds while typing, and sometimes it just dies, I have to restart), I will search the bug reports to see if they are already reported. Unfortunately I couldn't find yet which runner causes either of the bugs.