Aug 11

making firefox work with syzygy

The good folks at Google have written a clever tool called Syzygy, which is part of the Sawbuck project.  The best summary of Syzygy comes from its design document:

Syzygy is a suite of tools to perform profile-guided, function-level reordering of 32-bit Windows PE executables, to optimize their layout improved performance, notably for improved paging patterns.

Google wrote Syzygy for use with Chrome, but the tool is equally applicable to any large application where you want to improve performance…like Firefox.  In this case, we’re concerned with improving the layout of libxul, as that’s where the bulk of the Firefox code lives.  Working with Syzygy involves four major steps:

  1. Instrumenting the application binary in question;
  2. Running the application to collect profile data (function addresses along with invocation time);
  3. Passing the profile data through an ordering generator, which comes up with the order in which functions should be laid out in the optimized binary; and finally
  4. Relinking the application binary using the ordering from step 3.

Step 1 is pretty easy; Firefox just needs to be compiled with Visual Studio’s /PROFILE switch to ensure that the instrumenter has all the information it needs.  Steps 3 and 4 are likewise straightforward.

Step 2 appears to be the tricky part.  Being good–lazy–computer programmers, the Google folks wrote a number of scripts and programs to automate this process, as well as some benchmarking infrastructure.  However, the scripts are written with Chrome in mind; many places have Chrome-specific bits hardcoded.  This is, of course, totally understandable, but it makes using those scripts with other programs difficult.

Over the past couple of weeks, I’ve been working at making Syzygy cooperate with Firefox.  If you’re interested, you can see the modifications I’ve made in my sawbuck github project.  Things are working well enough that I can now run:

Debug/py/Scripts/benchmark --user-data-dir flobbity --no-preload --no-prefetch ~/ff-build/dist/bin/firefox.exe

(The --no-{preload,prefetch} options are required to work around Chrome-specific code that didn’t seem worth ripping out; the --user-data-dir specifies what profile to use when launching Firefox.)  After waiting for a minute or two, the benchmark script reports:

RESULT firefox.exe: SoftPageFaults= [23495, 32139, 23356, 23343, 23299, 23167, 23063, 23141, 23113, 23267]
RESULT firefox.exe: HardPageFaults= [1158, 10, 3, 3, 4, 2, 2, 2, 3, 2]

This is for an unoptimized binary, of course.  You can clearly see the OS’s page cache at work in runs after the first.

The scripts are not quite perfect yet.  In particular, the call traces necessary to perform reordering don’t seem to be generated, for some peculiar reason that I haven’t ferreted out.  Also, the script will indiscriminately kill any Mozilla-related apps running along with the Firefox instances being benchmarked; I couldn’t find any good way to limit the killing to windows associated with a particular profile.  (IIUC the Chrome code correctly, it sets the window text of a hidden window to the full path to the profile directory in use.)  But a good bit seems to work; hopefully progress will come faster now that the groundwork has been laid.

Aug 11

Hello world!

My name is Nathan Froyd and I work in Taras Glek’s group on performance-related things.  I’m working remote; I live in the wonderful city of Indianapolis, Indiana.

I started working at Mozilla back in mid-June, but took quite some time off due to cardiac arrest from streptococcal myocarditis.  Fortunately I came through that OK, and folks at Mozilla have been very helpful and understanding during my hospitalization and recovery.  I’ve been back to work for a couple of weeks now and finally feel like a Mozilla employee. 🙂

In my previous work, I worked on the GNU toolchain at CodeSourcery: GCC optimizations, both general and PowerPC-related; maintaining the PowerPC ports internally; C++ frontend diagnostic improvements, like function overload resolution failure explanation and better missing semicolon diagnostics; GDB porting; and supporting the toolchain on popular embedded platforms (across the x86, ARM, PowerPC, MIPS, SPARC, and SH architectures).

I also worked on some of the software architecture bits of GCC.  One of the patches I’m happiest with was a patch series to slim down how GCC represents expressions and constants internally.  I’m looking forward to working on similar software architecture patches at Mozilla.

Outside of work, I enjoy spending time with my family; I have three daughters and they keep my wife and I busy!  (I like to say that I am thoroughly outnumbered in my house–even the cat is a girl.)  I love to read: sci-fi, fantasy, history, philosophy, and theology books all grace my bookshelves.  When I do feel like programming outside of work, I enjoy working with Common Lisp and SBCL.  And finally, I recently started playing World of Warcraft once again.