{"id":1298,"date":"2011-01-10T16:03:04","date_gmt":"2011-01-10T15:03:04","guid":{"rendered":"http:\/\/glandium.org\/blog\/?p=1298"},"modified":"2011-01-10T16:03:04","modified_gmt":"2011-01-10T15:03:04","slug":"reducing-firefox-startup-io-using-system-libraries","status":"publish","type":"post","link":"https:\/\/glandium.org\/blog\/?p=1298","title":{"rendered":"Reducing Firefox startup I\/O using system libraries"},"content":{"rendered":"<p>After establishing <a href=\"\/blog\/?p=1269\">how I\/O affects startup<\/a> and exploring <a href=\"\/blog\/?p=1296\">some ways to improve the situation<\/a>, I wanted to check another obvious, yet not so practical for Mozilla, way of reducing startup I\/O.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>As a reminder, here are the startup times with a plain Firefox 4.0b8, as collected in <a href=\"\/blog\/?p=1269\">previous<\/a> <a href=\"\/blog\/?p=1296\">posts<\/a>:<\/p>\n<table class=\"table\">\n<tr>\n<th><\/th>\n<th>Average startup time (ms)<\/th>\n<\/tr>\n<tr>\n<th>x86<\/th>\n<td>3,228.76 \u00c2\u00b1 0.57%<\/td>\n<\/tr>\n<tr>\n<th>x86-64<\/th>\n<td>3,382.0 \u00c2\u00b1 0.51%<\/td>\n<\/tr>\n<\/table>\n<p>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):<\/p>\n<blockquote><p><code>ac_add_options --with-system-zlib<br \/>\nac_add_options --with-system-bz2<br \/>\nac_add_options --enable-system-sqlite<br \/>\nac_add_options --enable-system-cairo<\/code><\/p><\/blockquote>\n<table class=\"table\">\n<tr>\n<th><\/th>\n<th>Average startup time (ms)<\/th>\n<\/tr>\n<tr>\n<th>x86<\/th>\n<td>3,179.86 \u00c2\u00b1 0.44%<\/td>\n<\/tr>\n<tr>\n<th>x86-64<\/th>\n<td>3,326.5 \u00c2\u00b1 0.51%<\/td>\n<\/tr>\n<\/table>\n<p>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.<\/p>\n<p>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:<\/p>\n<blockquote><p><code>ac_add_options --with-system-nspr<br \/>\nac_add_options --with-system-nss<\/code><\/p><\/blockquote>\n<table class=\"table\">\n<tr>\n<th><\/th>\n<th>Average startup time (ms)<\/th>\n<\/tr>\n<tr>\n<th>x86<\/th>\n<td>3,086.74 \u00c2\u00b1 0.48%<\/td>\n<\/tr>\n<tr>\n<th>x86-64<\/th>\n<td>3,226.3 \u00c2\u00b1 0.59%<\/td>\n<\/tr>\n<\/table>\n<p>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.<\/p>\n<p>Let's now go even further and enable all currently supported flags remaining, except libpng, as already explained:<\/p>\n<blockquote><p><code>ac_add_options --with-system-libevent<br \/>\nac_add_options --with-system-libvpx<br \/>\nac_add_options --with-system-jpeg<br \/>\nac_add_options --enable-system-hunspell<\/code><\/p><\/blockquote>\n<table class=\"table\">\n<tr>\n<th><\/th>\n<th>Average startup time (ms)<\/th>\n<\/tr>\n<tr>\n<th>x86<\/th>\n<td>3,152.26 \u00c2\u00b1 0.74%<\/td>\n<\/tr>\n<tr>\n<th>x86-64<\/th>\n<td>3,270.9 \u00c2\u00b1 0.52%<\/td>\n<\/tr>\n<\/table>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>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:<\/p>\n<blockquote><p><code>ac_add_options --enable-shared-js<\/code><\/p><\/blockquote>\n<table class=\"table\">\n<tr>\n<th><\/th>\n<th>Average startup time (ms)<\/th>\n<\/tr>\n<tr>\n<th>x86<\/th>\n<td>2,887.48 \u00c2\u00b1 0.55%<\/td>\n<\/tr>\n<tr>\n<th>x86-64<\/th>\n<td>2,990.64 \u00c2\u00b1 0.65%<\/td>\n<\/tr>\n<\/table>\n<p>(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)<\/p>\n<p>That's totally worth it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;t come from Mozilla (though a large part [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25],"tags":[23],"class_list":["post-1298","post","type-post","status-publish","format-standard","hentry","category-planet-mozilla","tag-en"],"_links":{"self":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1298"}],"version-history":[{"count":32,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1298\/revisions"}],"predecessor-version":[{"id":1473,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1298\/revisions\/1473"}],"wp:attachment":[{"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/glandium.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}