PIM Sprint, Calendar progress and Akonadi

by markg85

Hi,

First of all, a nice picture of all the people attending the the spring 2014 pim sprint.
pim_group_picture_spring_2014

There will be a dot story later outlining what all happened during this sprint. For this blog post i’m merely focusing on what i did.

Optimize akonadi to be faster overall

Yeah, lets start with Akonadi..
tl;dr : I failed at optimizing anything.

The longer story is more interesting though.
While i wasn’t able to profile akonadi and fix or change hot code paths to be either faster or called less often (or both), i was able to identify one massive hot spot in Akonadi.

I will leave the technical details out because they aren’t quite clear to me*, but my (fairly simple) profiling does show me one massive bottleneck that could potentially speed up things quite significantly**. That is quite clear in the following picture:
akonadi_profiling

What you see here is the start of akonadi when it only has one maildir folder (a dump from the kernel mailing list) of about 80.000 mails. The most time is – obviously – being spend in libmysql, but there is also a lof of time that is being spend in creating QSqlQuery objects and query strings. In fact, much of the malloc calls that you see in the screenshot are caused by QString. What you also see is 6.2 million calls to QSqlQuery::value(int). Which is imho way to much for a maildir folder with just 80.000 mails. Mind you, i have nothing else setup so that maildir is all there is.

6.200.000 / 80.000 = 77,5 calls to QSqlQuery::value(int) which is just insane. Next up is further investigate why this is happening and see if there is a way to reduce this significantly. The most calls i would expect to QSqlQuery::value(int) is 10 per mail so that would be ~800.000 calls to QSqlQuery::value(int). Add to that that each mail has 3 akonadi database entries which would raise the theoretical maximum to 2.400.000 max for QSqlQuery::value(int).

Other then that i can’t figure out why it has so many more calls. I am still researching this issue and hope to find some reason why it’s this high. There is most certainly room for optimization here once i know how to handle this code. Right now i just know too little about this part to make a sane conclusion or even go as far as posting a patch. To be continued at some later point.

* disclaimer: i’m tempted to just ignore akonadi and leave that to the people who really know what they’re doing in there. I’m more at home in “using” akonadi classes instead of optimizing the gazillion files behind them.
** This is a profile of akonadiserver which is already quite fast. There is much to win in optimizing it, but it doesn’t have to be optimized.

Finally find a way to draw multiday events in QML (calendar stuff)

During the last PIM sprint it became painfully clear that QML is just not fit for handling multiday events as you know them in KOrganier, Mac Mail and some other mail applications. I gave up the pure QML approach at that time to revise it later (this sprint).

I’ve had the suggestion – quite a few times – to just align rectangles for multiday events in QML. While that is certainly a possibility, it’s not my preferred way of creating it. If you do it in pure QML then you need a _lot_ of javascript glue code to make it work. That in turn will make it more difficult to maintain (since you have lots of code) and will likely be hunting you back later on in terms of performance and scalability. But if you really are interested in how something like that is done in pure QML, then please look at the great length this QingfengCalendar has gone through to make it work. So it can be done.

I’m going for the C++ approach in sending QRect objects to QML which it would read and use in a repeater to place and position Rectangle{} objects. That seems like the easiest approach which is fairly simple from the C++ side. But how do i do that? Well, that’s a question i didn’t know how to answer. That’s where i’ve had some wonderful help of Sergio Martins.

Basically it boils down to this structure:
“CalendarEvents” class
– contains all the events within a given date range.

“EventRectangles” which has a CalendarEvents models as it’s source.
– This class would translate events to QRect objects and an ID to go back to the initial event as it was known in “CalendarEvents”.
– So for an event that is spread over X number of days, you would get an X number of QRect objects.

Implementing this is not that difficult but it requires some time to get it right since you need to re-implement some functions and play with Qt’s very annoying QModelIndex stuff. This class (EventRectangles) then listens to all Additions, insertions and updates that it reveives from the CalendarEvents source model and applies that to the rectangle objects. QML is then simply drawing the rectangles.

I have a very crude prototype of it working, but i need to work on it a bit more to get it working properly.

So that’s a nice bit of progression for this sprint. Not as much as i’d like, but good enough.

On to the frameworks sprint which starts in 20 days. I’m really looking forward to that sprint. Showcasing the current progress of Accretion, discussion my changes for KIO in terms of new classes for file/folder listing and probably more tons of fun stuff.

Cheers,
Mark