My blog has been moved to

Friday, September 11, 2009

SVG: parsing and content optimization

A few weeks ago, just for a change (between the usual QtWebKit bug-fixing and patches juggling), I did take a look at our QtSvg module. According to some internal reports, QtSvg is not fast enough when parsing a large and complicated SVG. Of course, slow is relative, slow to what. And arguably, parsing time is not as important as rendering time. But if you stash your user-interface elements in some sort of SVG theme, loading time becomes a factor (caching the pixmaps whenever possible also helps). Of course, reduced size served in a web server can decrease the bandwidth as well (think of all the SVGs in Wikipedia).

Still, I decided to have a look, just in case there are low-hanging fruits I can grab. And I was right, far from being an SVG expert, with just two days of work I managed to squeeze its performance a bit, which you'd enjoy already in the recent 4.6 preview.

The chart above - shorter is better - represents the comparison of the time spent in QSvgRenderer::load(), measured using CPU tick counter (in millions of ticks), comparing Qt 4.5 and 4.6. I also tested some other files as well, see the bigger bar charts. In all measurements, the 95% confidence intervals were well below 1%. In-house Theme refers to an internal SVG that unfortunately I can't share. Tiger is the SVG version of the famous head in PostScript (taken from GNU GhostScript), something I have shown before. Imperial Coat of Arms of France is another complex SVG, from Wikipedia Commons. World Map is the public domain blank grayscale world map from Wikipedia. There are a bunch of other test files I used, they mostly show the same improvements.

As you can see, Qt 4.6 would enjoy a bit of speed-up (in some cases up to 1.4x) when loading and parsing SVG.

However, I did not stop there. For the fun of it, I quickly hacked a Qt-based, command line SVG minifier, dubbed SVGMin. More about it can be read in the detailed Quick Start, but basically it tries to eliminate redundant garbages which have no effect whatsoever in the final rendering.

What follows is the chart showing the same type of measurement but I added the result with the minified SVG (see also the full comparison chart). The result should speak for itself:

I plan some more improvements to the SVG minifier, for example collapsing a single grouped element (<g><path ...></g> makes no sense), group a bunch of nodes with similar attributes (no need to duplicate the same fill colors over 100 circles), remove useless attributes (why there is fill-* for fill:none?), and many others. Hold your breath.


Jos said...

Great, SVG in Qt is very important and speedups welcome. What framerate do you get on the svg from this post:

boulabiar said...

Nice work ! it would increase next KDE release speed.

You haven't done a test for Qt4.5+Minifier ?

and when reducing SVGs, don't forget that order has signification. Rendering of an element on top of another depends on the order of parsing.

Ariya Hidayat said...

@Jos: Maybe I miss it, but I did not optimize rendering, only loading.

Ariya Hidayat said...

@boulabiar: Qt 4.5 + minified is left as an exercise for the reader?

And yes, as stated in the svgmin project site, the optimization is designed to have no effect on the final rendering.

Jeff Schiller said...

I'd be curious how your SVG minifier compares to Scour:

Ariya Hidayat said...

@Jeff: SVGMin is in its early stage and Scour is still better at producing smaller files.

Jos said...

@ariya ah, i indeed missed that it was for loading

Muhammad Younis said...

Very useful information, nice shearing,