gwtBox2d, Worker Threads, and SpiderMonkey

I’m going to try and keep this update short so that I actually finish editing it and it can be published. I’ve also been inspired by David Humphrey’s recent posts about his work to expose <audio> data in Firefox (and his efforts to get his students contributing to open source projects. and his baking.); as long as I’m thinking these things to myself, I might as well write them down. All benchmark times listed below are on my old 2 GHz  Core Duo and should be treated as only coarsely measured.

Really briefly, I’ve been “porting” the Box2D physics library (via JBox2d) to Javascript. Much like the existing Box2DJS, I’m cross-compiling, not from (the perhaps saner choice of) ActionScript, but from Java via the Google Web Toolkit. I put “porting” in quotes because not only is GWT doing most of the heavy lifting here, the JBox2D library was already well insulated from the JRE. Moreover, the maintainers of JBox2D have long worked hard to pool objects wherever possible to cut down on JVM garbage collection, which is also key in a Javascript application. To get an initial build working I had to do very little, replacing some thread-safety code that relied on JRE primitives and a few assorted methods unsupported by JavaScript.

My first demo ran well in Chrome but dragged horribly in Firefox 3.5. Due to the instruction- and branch- heavy nature of the code, SpiderMonkey had difficulty keeping up with the traces it needed to perform and, based on my best analysis of the analysis going on on Mozilla’s Bugzilla, the Javascript engine ended up spending more time looking through traces than running them and, to make matters worse, would occasionally garbage collect compiled code and have to start from scratch. Unfortunately I looked into all of this several months ago, before diving into the wild world of cross-browser CSS transforms, so what I’m writing now is just the best I can recall. Bugs 504829 and 504881 are the most relevant I can find right now, but neither is resolved. Something must have changed, though, because I’m getting a huge performance boost in Firefox 3.6b5. While still taking four to five times longer than Chrome to compute the same step, after some retooling and optimizations the library is highly usable in the latest Firefox.

Interestingly, drawing the scene to a Canvas in Chrome takes just as long as a physics simulation step (math in V8 is fast). If the UI hangs and the Canvas object doesn’t update, you just lose a frame of animation. The problem comes when simulation steps are delayed; this causes the world to play out in slow motion as a shorter time period is simulated than actually passes. Meanwhile, in Firefox, long (40ms) calculation times cause the rest of the interface (including that of the browser) to feel sluggish. Finally, the culprit in all of this is a script that never touches the DOM or the Window, except to update a small set of object positions. This all adds up to a perfect use case for Worker scripts.

There are a few implementations using Workers or something like them in GWT, notably GALGWT, utilizing the WorkerPool in Google Gears, and the newly released Speed Tracer. I’ve adapted code from Speed Tracer and GWT’s default single-script linker to compile the gwtBox2d library to a Worker, using JSON to pass transformation data (per simulated body) back and forth. It runs just a touch slower in Chrome, but this is made up for by the fact that the interface and the simulation are now decoupled. However, even in the latest Firefox, 3.6b5, the old SpiderMonkey problems are showing up again! The calculation time per step quickly balloons to over 600ms. What really cements the fact that this is the same problem is that, when the Script panel of Firebug is enabled (thereby disabling tracing and JIT compilation in SpiderMonkey), calculation times drop to about 80ms, only twice the time of a step computed in the main thread. From this we can also deduce that a) pure math is fast, even in “interpreted” mode and b) the main-thread time of 40ms is probably “slow,” i.e. my code is already exiting traces like crazy anyway, it just isn’t exploding the tracer in the process.

Anyway, this was pretty disappointing. Clearly Firefox is executing Javascript slightly differently within Workers than without, so perhaps recent patches to main-thread Javascript execution couldn’t be applied there. Automatically generated code isn’t exactly the best test case to submit to Bugzilla, so I’m not sure the best place to take this problem yet. Moreover, even with a submitted bug, there’s no way a change will make it into 3.6 at this point, so it will be a while before Firefox gets a nice Worker-based physics library. In the meantime, I’ll work on making the JSON interface and drop-in nature of the library compelling enough to make it a worthy goal (Box2DJS is already used as a test case of sorts, filed under “would be nice to have running perfectly at some point in the future”) and maybe get a copy of the trace-debug build of Firefox so that, if its not a fundamentally algorithmic problem, I can cut down on the code that’s been kicking SpiderMonkey around.

You can see (almost) all the code over at the (otherwise threadbare) gwt-ns library on Google Code.

This entry was posted in Uncategorized and tagged , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">