JS Development Newsletter 11/23-11/29
Help Firefox get incremental GC
Bill McCloskey has incremental GC working as a prototype in the larch branch. The current version is probably pretty crashy but does show the pause time improvements on some sites.
It would help Bill a lot to get a list of sites that have big GC pauses now in Firefox. He needs sites that will do a lot of GC so he can tune incremental GC to perform well, and also test for stability. So, if you know of any good sites that suffer from GC pauses, please post them to https://bugzilla.mozilla.org/show_bug.cgi?id=702495 or email me (email@example.com). Some hints on what to look for:
Sites that are animation-heavy or JS-heavy are the likeliest to get GC pauses. One example is Flight of the Navigator, which will show some brief pauses or glitches in the animation.
The big news for this week is that the tracejit has been been retired: jstracer.cpp and the nanojit directory have been removed from the tree. With JM+TI, the tracer doesn’t run, so it wasn’t helping performance, but removing it reduced our code size (by 0.5MB in one measurement on Linux) and complexity, which will help us add other optimizations faster. For example, the ObjShrink project removes some things that the tracer depends on, so if we kept the tracer, we’d have to do a bunch of work to make the tracer work correctly, which wouldn’t even help us because the tracer doesn’t run for content.
I’ve seen a few commenters express disappointment about the retirement of the tracer, saying things like, too bad it didn’t work out. But I don’t see it that way. We are constantly replacing code inside the engine as we improve it–I think it’s been estimated in the past that about 25% of the engine is replaced per year–so the expected lifetime of any particular piece of code is something like 4 years. JITs are hot right now, so they are prime candidates for improvement and replacement. TraceMonkey has been in the tree for about 3.5 years. JägerMonkey might not even make it 2 years before being replaced by IonMonkey.
I still remember that not long after I started at Mozilla, I got to go to a few meetings in building S (or was it K?) with Brendan to talk about a tracing compiler for JS with people from Adobe like Edwin Smith and Rick Reitmaier, and meeting Andreas and Michael Bebenita and Michael Franz; learning why tracing nested loops is hard, and the different solutions of ‘outerlining’ and nested traces; and hearing about how a Game of Life benchmark generated a large number of traces. I was working on some static analysis stuff at the time but I thought doing a compiler for JS sounded amazing, so I followed along. I was excited enough to read their code carefully and do a 5-part series on Tamarin internals on this blog.
I’m not sure exactly how I got started working on TraceMonkey myself, but I think I jumped in to fix some crashes and performance faults to help get it ready for release. What I remember best about that is spending an entire week on one strange intermittent performance regression that depended on the length of the command line used to run the test and eventually turned up a data alignment problem that boosted the performance of the whole system when fixed, still one of my proudest moments in Mozilla hackery. I did a lot of other work on the tracer too, mostly bug fixes and small optimizations, but I also implemented support for tracing pretty much any kind of closure or closure variable over a summer.
So TraceMonkey was my (and David Anderson’s) personal training ground in industrial-strength JIT architecture, implementation, and performance analysis, which fed straight into JägerMonkey and now IonMonkey. Andreas turned TraceMonkey into a PLDI paper, which may have something to do with the increased interest the academic community has taken in JS since then. TraceMonkey gave Firefox fast JS for versions 3.5 and 3.6, and provided an essential part of the platform for David Humphrey and his colleagues to make a ton of cool demos. And that’s pretty great.
Chris Leary landed function inlining, the last of the major optimizations in the initial plan. Sean Stangl landed on-stack replacement (OSR), a key piece of infrastructure, which is required to patch in reoptimized or deoptimized compiled code while running (JM+TI also has OSR).
Small but nice landings
When Firefox runs GC, it can optionally do a “shrink GC”. A shrink GC does a regular GC, then releases free GC-controlled memory pools to the OS, thus reducing the amount of memory used by the browser. If the browser is about to allocate more memory, then it will have to claim that back from the OS immediately, slowing things down, so Firefox doesn’t do shrink GCs very often, mostly when it really expects memory usage to go down for a while. Terrence Cole landed a patch to trigger shrink GC on system memory pressure events, which will hopefully help cut memory usage when it’s most needed.
Finally, Alon Zakai added a printErr function to the JS shell, just like print but going to stderr.