Over the last months, Lanedo has received multiple customer requests to improve LibreOffice where it isn’t performing very well. During the course of this time we’ve been investigating many bug reports and covering a lot of the code base.
We all want our software to be fast and responsive. LibreOffice is no exception and is often seen by users as a big, huge and sometimes slow software. The incredible work done by Michael Meeks et al vastly improved the situation over the years and created opportunities to make LibreOffice even faster.
Achieving better performance is probably one of the most complicated task in today’s software engineering. Is the program slowed down by unnecessary IO (reading/writing files on a disk)? By a concurrency issue like multiple threads trying to access the same resource at the same time? Is it a rendering issue? Is the measured speed related to the perceived speed by the user?
Complexity and the need for profiling
Bug #39179 is a perfect example of this hidden complexity. The problem is simple: LibreOffice takes a long time to open a particular document. But beyond that symptom, the various comments and analysis show how hard it is to pinpoint a particular cause. Why is this document so special? What is the culprit? Let’s start an investigation!
Inexperienced programmers tend to go with their intuition and optimize the part of the code where they think the most time is spent. This could result in days of work on a function where, in fact, only 1% of the time is really spent. Every programmer has done this at least once in their career. But the lesson here is: before optimizing, you have to measure to understand your situation fully. Trying to grasp where the software spends its time is called profiling. No serious optimization work can be done without profiling.
Creating and Understanding Profiling Data with Chrome
Getting the data from profiling is one thing. Being able to understand them is another. A few months ago, an article by Colt McAnlis highlighted that Google’s browser Chromium has an integrated viewer for profiling data. Over the past few days I decided to toy with it to better understand LibreOffice performance.
The first step was to get the data by inserting hooks in the LibreOffice code that were under investigation.
Profile::Event(this, “Timeout”, mName, ProfilePhase::BeginEvent);
maTimeoutHdl.Call( this );
Profile::Event(this, “Timeout”, mName, ProfilePhase::EndEvent);
In this example, “Timeout” is the category of the event, mName its name and ProfilePhase is self-explanatory. To match begin/end events, the category and name have to match. The Profile::Event function is a home-made function that writes to a JSON file containing all the performance data. The format of this JSON file allows it to be opened with Chromium or an independent viewer (also from Google).
The first results
Being able to embrace the situation at a glance is very informative. For example, LibreOffice uses a lot of timers and seeing them displayed like this allows us to quickly discover recurring patterns.
You may witness that after loading a document, SwDoc::maIdleTimer is doing some layout refinement. You can also observe that the rendering is done by starting the ImplFrameData::maPaintTimer timer, which has a 30 ms timeout.
Out of curiosity, I probed around the call to g_main_context_iteration(). After visualizing the pattern, I realized that LibreOffice was waking up to sleep() even when there was nothing to do. I have written a patch to address the issue but certainly more work is needed in this area.
Investigating bug #39179
But let’s go back to bug #39179 where opening a particular document is really slow. After adding a few probe points, I produced a JSON file and using that we can zoom in on the graphic to see where the time was spent.
Here the root cause of the problem is obvious. This document is full of footnotes which are incredibly expensive to load. No further questions, the problem is there, before our eyes. Finding a solution, on the other hand, is left as an exercise to the reader.
Integrating profiling in LibreOffice?
Of course, the same conclusion could be reached using your favorite profiler but it requires at least symbols and some development experience. It is also mandatory for everybody that wants investigate a particular performance issue to be able to compile LibreOffice.
If properly integrated, as it is in Chromium currently (link only works in Chromium), this feature could be enabled in a release build and useful to users when reporting performance bugs. Binaries with profiling capabilities could be distributed allowing every single user to give profiling data about their own issues.
The code used to generate performance traces in the Chromium JSON format isn’t available yet but I will publish it shortly in a feature branch in the LibreOffice git repository for everyone to play with!
What is your pet peeve with LibreOffice performance?