I’ve been waiting to blog about this for a long time now. A fantastic new improvement to Mozilla’s JavaScript engine (SpiderMonkey) has landed. Code-named TraceMonkey this engine utilizes a techniques, called trace trees (PDF), which adds just-in-time native code compilation to SpiderMonkey.

A major goal of the project has been to set JavaScript up to compete with natively-compiled code, rather than simply against other interpreters. This means that we’re starting to see speeds that are completely out of this league when it comes to performance.

Results and Try it Yourself

Here are the results from four benchmarks to give you a taste:

The tests are:

If you want to try these out for yourself, just snag a nightly of Firefox 3.1, open about:config, and set the following preference to true:

javascript.options.jit.content

You should be, happily, in just-in-time tracing land. It’s still buggy (hence the reason for hiding behind the preference wall) but it should be good enough to handle most web sites.

What’s especially exciting is that this code is working on x86, x86-64, and ARM – which means that these improvements won’t be limited to just the desktop – you’ll be able to receive them on your mobile devices as well.

How Tracing Works

In simple terms tracing works by watching for commonly-repeated actions (such as loops, function calls, or type checking) and tries to optimize their resulting native code into the lowest number of actions. The premise is rather simple – and it’s an advance that we’ll probably see proliferate to many interpreters and engines in the upcoming years.

Andreas Gal published a paper (PDF) on the subject and Brendan Eich has written up a TraceMonkey-specific explanation.

Some of the improvements made by tracing include:

Function Inlining: Removing the overhead of function calls by simply replacing them with their resulting native code.

Type Inference: Removing checks surrounding common operators (like “+”) when the types contained within a variable are already known. This means that the engine will have already pre-determined, for example, that two strings need to be concated when it sees the “+” operator.

Looping: The overhead of looping has been grossly diminished. It’s one of the most common areas of overhead in JavaScript applications (common repetition of a task) and the constant determining of bounds and the resulting inner code is made negligible.

The code for this project has come from a number of places – one of which is coming from some code contributed to Mozilla, from Adobe: Tamarin Tracing, specifically the nanojit code that’s able to work a lot of this just-in-time magic.

Development

The work began just about 60 days ago, working with Andreas Gal of UC Irvine, to integrate the nanojit technology into Spidermonkey. You can hear more about the development from those that were involved: Andreas Gal, Mike Shaver, and Brendan Eich.

The full code can be found in the TraceMonkey mercurial repository (the commit to merge TraceMonkey into Mozilla core is massive, clocking in at about 4MB).

If you want to try running your own copy of TraceMonkey on the command-line, just follow the steps outlined here.

There is still a ton of work to be done. The incredible speed-ups that we’re seeing are only just the beginning. A lot can be done to improve how registers are currently being allocated which will provide even more speed-ups.

Right now there isn’t any tracing being done into DOM methods (only across pure-JavaScript objects) – but that is something that will be rectified. Being able to trace through a DOM method would successfully speed up, not only, math and object-intensive applications (as it does now) but also regular DOM manipulation and property access.

Ramification

So what does this all mean? It means that JavaScript is no longer confined by the previously-challenging resource of processing power. With this improvement it’s leap-frogged any sort of traditional and has gone head-to-head with computationally-powerful languages like C.

I fully expect to see more, massive, projects being written in JavaScript. Projects that expect the performance gains that we’re starting to see. Applications that are number-heavy (like image manipulation) or object-heavy (like relational object structures).

One area that I’m especially excited about is in relation to Canvas. The primary thing holding back most extensive Canvas development hasn’t been rendering – but the processor limitations of the language (performing the challenging mathematical operations related to vectors, matrices, or collision detection). I expect this area to absolutely explode after the release of Firefox 3.1 as we start to see this work take hold.

Seeing releases like this are absolutely exciting for me. JavaScript is absolutely the little-language-that-could – continually routing around any of its short-comings and blowing away all of its expectations. I look forward to using it for many, many, years to come.