Reducing Firefox startup I/O using system libraries

After establishing how I/O affects startup and exploring some ways to improve the situation, I wanted to check another obvious, yet not so practical for Mozilla, way of reducing startup I/O.

Firefox is a quite featured web browser, and fortunately, all the code in the Firefox tree doesn't come from Mozilla (though a large part does). Some parts of the code actually come from third party libraries, such as libpng for PNG support, libjpeg for (obviously) JPEG support, libsqlite3 for SQLite support (used, for example, for the awesomebar), or libcairo for part of the layout rendering.

Some of these libraries are also used in other software. For instance, Gtk+, the widget toolkit Firefox uses on UNIX systems, and used by the GNOME desktop environment, needs, directly or indirectly, libcairo for rendering, and libpng for icons. But these other softwares don't embed their own copy of the libraries: they use shared, system libraries.

There are several advantages doing so: they reduce memory footprint, because the library is loaded only once in memory (modulo relocations on data sections), they reduce maintenance overhead (you only need to update one copy for stability or security issues), and, you should have guessed where I'm going by now, they help reduce startup I/O: a system library that has been loaded by some other software doesn't need to be read from disk again when you start another application using the same system library.

Unfortunately, Mozilla distributes binaries that can run on a large variety of systems, which are not necessarily using the right versions of the libraries, and sometimes even, Mozilla patches some libraries it embeds to fix bugs or add features. One such example, the worst case, actually, is libpng, which is patched to handle APNG files. Libcairo also comes with some bug fixes, most of which, after a while, end up in the original libcairo. Anyways, as Mozilla can't really control which version of cairo, sqlite, etc. are installed on systems where Firefox is going to be used, the only way that works for us is to ship binaries that link against these internal (possibly modified) libraries.

Though the same logic could be applied to some other libraries which we do link against system versions of (such as Gtk+), they're, in practice, not so much a problem as sqlite and cairo, which are the most problematic libraries at the moment.

On non GNU/Linux platforms (excluding some other uncommon unix variants for Firefox users), system libraries are unfortunately not a common practice, and even if they were, most of the libraries Firefox uses internally are not shipped with the system. On (more or less) controlled environments, however, the story is slightly different. When you know what version of which libraries is shipped, it's easier to start using system libraries. GNU/Linux distributions are such environments, mobile OS (Android, Maemo/Meego) are, too.

I'm not interested in discussing here the support implications of GNU/Linux distributions shipping Firefox binaries linked against system libraries, though in practice, it creates less problems than some people may think. This post only aims at showing how using system libraries impacts startup times, how it could or could not be an interesting thing to investigate on mobile, and how GNU/Linux distributions practices are actually not hurting.

As a reminder, here are the startup times with a plain Firefox 4.0b8, as collected in previous posts:

Average startup time (ms)
x86 3,228.76 ± 0.57%
x86-64 3,382.0 ± 0.51%

The first set of system libraries I enabled are those that the default GNOME desktop environment as it comes in Debian Squeeze uses, except libpng, because the system library doesn't support APNG files (note that I installed libcairo from Debian experimental, as Squeeze doesn't have 1.10):

ac_add_options --with-system-zlib
ac_add_options --with-system-bz2
ac_add_options --enable-system-sqlite
ac_add_options --enable-system-cairo

Average startup time (ms)
x86 3,179.86 ± 0.44%
x86-64 3,326.5 ± 0.51%

It turns out there is not much gain, but at least, it's not a regression. Please note that libbz2 is actually not used in Firefox itself. It's only used in the upgrade program.

Let's go further: the clock applet coming with the gnome-panel uses a system copy of libnspr4 and libnss3, through libedataserver. Provided that these libraries are recent enough on the system, Firefox can actually use them, so let's add these:

ac_add_options --with-system-nspr
ac_add_options --with-system-nss

Average startup time (ms)
x86 3,086.74 ± 0.48%
x86-64 3,226.3 ± 0.59%

This had a much more noticeable positive impact. This is most probably due to the size and number of libraries involved, as currently, nspr and nss are respectively 3 and 8 separate library files.

Let's now go even further and enable all currently supported flags remaining, except libpng, as already explained:

ac_add_options --with-system-libevent
ac_add_options --with-system-libvpx
ac_add_options --with-system-jpeg
ac_add_options --enable-system-hunspell

Average startup time (ms)
x86 3,152.26 ± 0.74%
x86-64 3,270.9 ± 0.52%

Unsurprisingly, it has a negative impact, most probably due to the additional disk seeks that each of these library induces. The good news is that it doesn't get slower than the original Firefox build, and is actually still slightly faster.

There are more libraries that Firefox embeds and could be using system libraries instead, but there aren't flags for them yet. At the very least, and if I recall correctly, libogg is loaded by the GNOME desktop environment through libcanberra for event sounds, so there could be some more possible gain there.

However, it's not entirely clear from the above figures whether that would be worth on mobile OS, but I'm not putting too much hope there. I'll first need to collect some more data first, such as which libraries are used after a system boot, and what versions are provided.

On desktops, though, we can go even much further. In the 3.x days, and earlier, Firefox's javascript engine was shipped as a separate library in the Firefox directory. In recent 4.0 betas, it is now statically linked into libxul.so. But, the future GNOME desktop, based on GNOME shell, will be using Firefox's javascript engine. Some distributions plan to use a separately packaged javascript library for that purpose. In Debian, I'm still planning to keep Firefox shipping the javascript engine as a separate, system library, so let's see what that means for startup time:

ac_add_options --enable-shared-js

Average startup time (ms)
x86 2,887.48 ± 0.55%
x86-64 2,990.64 ± 0.65%

(disclaimer: this was not measured with an actuall GNOME shell, but with the current GNOME desktop, and a script reading the javascript library file to force it in page cache. Arguably, an actual use of the library may be loading less of it in page cache)

That's totally worth it.

2011-01-10 16:03:04+0900

p.m.o

You can leave a response, or trackback from your own site.

18 Responses to “Reducing Firefox startup I/O using system libraries”

  1. Nuss Says:

    I have no idea what I’m talking about here, but wouldn’t it be possible (with some effort and some magic) to make nspr and nss respectively into one single library each in order to reduce I/O?

  2. antistress Says:

    very interesting, thanks

    Moreover, i didn’t knaow that GNOME 3 will use Firefox’s javaScript engine :-)

  3. Simon Says:

    @antistress – yeah, Gnome Shell runs on gjs which is a wrapper around SeaMonkey. Kind of annoying, actually, given that it’s the one piece of Gnome that favours Mozilla over Webkit – other parts of Gnome use seed (based on Webkit) for javascript support, so the inconsistency is a nuisance.

  4. Dan Says:

    Can you run the testsuite with all of the internal libraries replaced with system libraries? I wonder how many tests would fail.

  5. Kümmelreiter Says:

    I thought this post would be about the recent breakage of –enable-system-cairo in trunk…

  6. antistress Says:

    Indeed, i believe that WebKitGTK+ for instance makes use of SquirrelFish. This is a very strange decision

  7. glandium Says:

    Kümmelreiter: What recent breakage? Ok, found: https://bugzilla.mozilla.org/show_bug.cgi?id=363861#c132

    Dan: I do run xpcshell-tests, reftests, crashtests and jsbrowsertests on a regular basis on 3.5 and 3.6 with system libraries with no noticeable failures. I ran the same testsuites on 4.0 recently with a few failures, but it looks like most are related to the firefox-on-xulrunner setup.
    There is, however, a known issue with system cairo that the testsuite doesn’t catch: https://bugzilla.mozilla.org/show_bug.cgi?id=589737

  8. njn Says:

    This is all good stuff, but I wonder if Firefox’s reputation for slow start-up is mostly due to the extreme cases — ie. those people that have screwed up profiles (or whatever) and so it takes 30 seconds or 2 minutes or something ridiculous to start up.

    In comparison, I doubt most people notice the difference between 3.2s and 2.8s.

  9. glandium Says:

    njn: that is another front that is being explored separately.

  10. pd Says:

    Would this be more feasible if Mozilla had a better, faster working relationship with library developers? Sounds to me like Mozilla is writing patches on top of libraries that could be integrated into the libraries themselves faster. What is the hold up in this regard?

  11. glandium Says:

    pd: even if patches would be upstreamed faster, there is still the problem that you won’t get them applied on your old distro. And all doesn’t boil down to patches, there are also new upstream APIs that Firefox may be using but that your distro doesn’t provide just yet.

  12. Ted Mielczarek Says:

    pd: on the contrary, Mozilla upstreams virtually all of our patches to third party libraries, and in many cases Mozilla developers are also active committers to the upstream repositories. There’s just the dual problems of releases (Firefox vs. the libraries) not being synchronized, as well as the lag time for Linux distributions to update their included versions of the libraries.

  13. skierpage Says:

    You need a layer under Firefox that guarantees that all the right system library versions are available, then just depend on an up-to-date version of that. Oh, wait, you built it already, it’s called XULRunner, and I think most distros package it and I hope do a good job of optimizing it. Bring back the dream ;-)

    Does anyone make a FirefomeOS, a Linux distro that is solely focused on running Firefox and a few supporting extensions and XUL-based apps to fill out the desktop? (I know, I should try browserlinux.com and SplashtopOS)

  14. Anon Says:

    Wow – it almost feels like you are going the opposite way to Chrome on this. Don’t most Linux distros compile the Firefox against they distribute themselves against the system libraries (mainly for maintenance purposes) though? Don’t you find that these are slower?

    This blog post reply to a Fedora dev ( http://spot.livejournal.com/312320.html?thread=1470976#t1470976 ) says why Chrome is bundling everything. If the distributions are distributing it (for fixed versions of their distribution) then it sounds like some of these may stop applying.

  15. glandium Says:

    > Don’t most Linux distros compile the Firefox against they distribute themselves
    > against the system libraries (mainly for maintenance purposes) though?

    They do.

    > Don’t you find that these are slower?

    My experiment above shows this is not true. Or at least that there may be reasons why they are slower, but system libraries aren’t part of them.

  16. Tony Mechelynck Says:

    –with-system-nspr doesn’t work, at least for me (and for SeaMonkey on openSUSE Linux 11.3) it doesn’t. I get the following error in js/src/configure :

    configure: error: –with-system-nspr and –with-nspr-libs/cflags are mutually exclusive.

    *even* with

    ac_add_options –with-system-nspr –without-nspr-libs –without-nspr-cflags

    in which case the command-line for the failed configure shows that –with-nspr-flags= –with-nspr-libs= have been added, overriding my -without-…, as follows:

    configure: warning: Recreating autoconf.mk with updated nspr-config output
    configuring in js/src
    running /bin/sh /root/.build/mozilla/comm-central/mozilla/js/src/configure –enable-application=suite –enable-calendar –enable-debug-symbols=-gdwarf-2 –disable-install-strip –disable-optimize –enable-debug –enable-libxul –enable-ipc –disable-tests –disable-codesighs –disable-official-branding –with-branding=suite/branding/nightly –disable-update-channel –enable-chrome-format=omni –with-system-zlib –with-system-bz2 –with-system-nspr –without-nspr-libs –without-nspr-cflags –with-system-nss –with-system-libevent –with-system-jpeg –enable-system-hunspell –enable-shared-js –disable-system-sqlite –disable-system-cairo –without-system-libvpx –enable-application=suite –enable-calendar –enable-debug-symbols=-gdwarf-2 –disable-install-strip –disable-optimize –enable-debug –enable-libxul –enable-ipc –disable-tests –disable-codesighs –disable-official-branding –with-branding=suite/branding/nightly –disable-update-channel –enable-chrome-format=omni –with-system-zlib –with-system-bz2 –with-system-nspr –without-nspr-libs –without-nspr-cflags –with-system-nss –with-system-libevent –with-system-jpeg –enable-system-hunspell –enable-shared-js –disable-system-sqlite –disable-system-cairo –without-system-libvpx –enable-application=../suite –disable-official-branding –with-branding=../suite/branding/nightly –enable-threadsafe –enable-ctypes –with-nspr-cflags=’-I/root/.build/mozilla/comm-central/obj-i686-pc-linux-gnu/mozilla/dist/include/nspr’ –with-nspr-libs=’-L/root/.build/mozilla/comm-central/obj-i686-pc-linux-gnu/mozilla/dist/lib -lplds4 -lplc4 -lnspr4 -lpthread -ldl’ –with-dist-dir=../../dist –prefix=/root/.build/mozilla/comm-central/obj-i686-pc-linux-gnu/mozilla/dist –with-sync-build-files=/root/.build/mozilla/comm-central/mozilla –enable-jemalloc –cache-file=../../.././config.cache –srcdir=/root/.build/mozilla/comm-central/mozilla/js/src

  17. glandium Says:

    Tony: that’s because your system nspr version is too old.

  18. Tony Mechelynck Says:

    ah, I see; so were cairo and mysql, and I couldn’t even find libvpx. Well, openSUSE Linux 11.4 is scheduled for 10 March, I may try again after that.

Leave a Reply