Main menu:

Site search



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 or email me ( 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.

You can test whether pauses are caused by GC by going to about:config and setting the pref javascript.options.mem.log to true, then opening the Error Console (Tools/Web Developer/Error Console or your local equivalent of Ctrl+Shift+J), and clicking Messages. The console will list all the GC (and CC–cycle collector) events, including timing data. If you see a pause or glitch, and a GC message prints out at the same time, then it was probably a GC pause.

Adieu, jstracer.cpp

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.


Comment from Ferdinand
Time: November 30, 2011, 1:12 am

About the GC pauses. Lately I have a lot of pauses in minefield while scrolling, opening tabs, switching tabs. It makes Firefox feel really sluggish. And this is with gpu acceleration and smooth scrolling. The hard part is I have over 25 tabs open so I can’t point to a single website. I do see spikes of 100% cpu that last less than a second. I have an ssd so I don’t think it is IO.

Comment from Ferdinand
Time: November 30, 2011, 1:34 am

Build 20111129 I am watching the Error Console Messages and while browsing I see 130ms to 270ms GC pauses every 5 seconds. Phenom II X4 940
CC(T+496.4) collected: 2644 (2644 waiting for GC), suspected: 2686, duration: 244 ms.

When I have 1 tab open I get:
CC timestamp: 1322645576597000, collected: 0 (0 waiting for GC), suspected: 75, duration: 18 ms.

Comment from Russell Keener
Time: November 30, 2011, 12:48 pm

I don’t know if it’s GC related but seems to perform worse in Firefox 8 and 9 as compared to Firefox 7. It has lots of small pauses in 8 and 9.

Comment from David Humphrey
Time: November 30, 2011, 3:03 pm

Thanks for this post, Dave, I really enjoyed it. It’s no exaggeration to say that all our audio, processing.js, webgl, demo, etc. work was done on the back of the tracer. It was my secret weapon from the moment Boris taught me how to read the TMFLAGS tea leaves 🙂 I made a lot of code go really fast by understanding how to tune my stuff to the tracer. I’m a bit sad to see it go, but amazed that you guys have managed to do so much better than it so quickly. Thanks for all your work on it. I think we proved a lot about the web and what it was capable of doing, thanks to it.