the birth of a faster monkey

Over the past year, JavaScript performance on the web has undergone a striking revolution. Virtually every browser has improved its engine to produce significant gains in execution speed; Firefox is about 3 times faster than Firefox 2 in various JavaScript benchmarks, for example. But of course, developer and user demand for performance is insatiable, and at Mozilla we demand it ourselves, since our application itself is largely and increasingly written in JavaScript. In addition to improving the performance of web applications, our work on JS performance in Firefox 3 made our own application snappier and more responsive.

We’re not done. In addition to continuing to work on our existing JavaScript interpreter (some 20% improved over Firefox 3 already), we’re also looking farther into the future of JS performance, and have some early news to share. Permit me, if you will, to set the stage:

Core primitives improved by 20-40x

These are the early results from a project we’ve been calling TraceMonkey, which adds native code compilation to Mozilla’s JavaScript engine (“SpiderMonkey”). Based on a technique developed at UC Irvine called “trace trees“, and building on code and ideas shared with the Tamarin Tracing project, a few of us have spent the last 2 months (and most of the last few nights) teaching SpiderMonkey some exciting new tricks.

The goal of the TraceMonkey project — which is still in its early stages — is to take JavaScript performance to another level, where instead of competing against other interpreters, we start to compete against native code. Even with this very, very early version we’re already seeing some promising results: a simple “for loop” is getting close to unoptimized gcc:

for loop: gcc 1070ms, js 910ms

Yesterday we landed TraceMonkey in the Firefox 3.1 development tree, configured off by default. We have bugs to fix, and an enormous number of optimizations still to choose from, but we’re charging full speed ahead on the work we need to do for this to be a part of Firefox 3.1. Depending on the benchmarks you choose, you might see massive speed-up, minor speed-up, or maybe even some slowdown — those latter cases are definitely bugs, and reporting them through bugzilla will be a big help.

Here are the current speedups of some common and uncommon benchmarks, as compared to Firefox 3: Apple’s SunSpider, the SunSpider “ubench” tests added for squirrelfish; an image manipulation demo; and a test of the Sylvester 3D JavaScript library doing matrix multiplication.

4 bench graph: sunspider at 1.8x, ubench at 22.4x, image manipulation at 6.5x, sylvester at 6.2x

There are many wins left in each one of those benchmarks, and we’ll be working on those through Firefox 3.1 and beyond: better code generation, more efficient guards, improvements to some data structures, parallel compilation, use of specific processor features, new optimization passes, tracing more code patterns, and many more. Right now we write all values back to memory at the end of every loop, for example, so there are some easy wins available in avoiding that — perhaps 2-3x on tight loop performance.

There’s lots more to write about why we chose tracing as the path to future performance, what to expect in terms of future work, how these sorts of performance gains can translate into new web experiences and capabilities, and what we’ve learned along the way. (One example out of left field: the static analysis tools are written in JavaScript, and apparently they are immensely faster due to even the current JIT work.) Look for posts about that from myself and other TraceMonkey hackers soon.

If you’re the sort of person who reads computer science papers, you may find the Hotpath paper to be of interest: it’s a great paper, and a great introduction to the art and science of tracing.

Thanks are especially due to Brendan, Andreas and David for making it fun to be the dumbest guy on the team; Andreas’ colleagues at UCI (Michael Franz, Mason Chang, Michael Bebenita, Gregor Wagner) for their advice and help; Ed Smith and the Adobe Tamarin team for their tech and wisdom; Rob Sayre, Vlad Vukicevic, Blake Kaplan, Boris Zbarsky and Bob Clary for testing and timely guidance; and the Mozilla developer community for letting us hold the tree closed for more than a day to get it landed.