ChipmunkJS and Emscripten
I've finally gotten around to compiling Chipmunk to JS using Emscripten to see what happens. It works great.
As a baseline, here's the first benchmark running in C:
Time(a) = 1451.45 ms (benchmark - SimpleTerrainCircles_1000)
The same benchmarks running with chipmunkjs in node 0.10.12 (v8: 3.14.5.9):
$ node bench.js
SimpleTerrainCircles 1000
Run 1: 22426
Run 2: 21808
(ie, 21 seconds, 15x baseline)
Using v8 head (v8: 3.19.18.5):
$ ../v8/out/native/d8 bench.js
SimpleTerrainCircles 1000
Run 1: 11248
Run 2: 12930
(8x baseline)
Emscripten (-O2 -DNDEBUG), v8: 3.19.18.5 in Chrome Canary:
Time(a) = 3967.12 ms (benchmark - SimpleTerrainCircles_1000)
(2.7x baseline)
In Firefox 22 (which has asmjs support) (Firefox nightly (25a) has about the same performance):
Time(a) = 2044.10 ms (benchmark - SimpleTerrainCircles_1000)
(1.4x - only 40% slower than C!!!)
The V8 team is actively working on making asmjs code run faster in v8. They don't want to have a special 'asm.js mode' like firefox does - instead they're adding optimizations which can kick in for asmjs-style code (source: insiders on the Chrome team). I expect Chrome performance to catch up to firefox performance in the next ~6 months or so.
Notes:
I didn't make any changes to chipmunk (although I did bump chipmunkjs tests runs back up to 1000 to match chipmunk). My test code is here
I compiled the benchmark code from C using emscripten. If your game is written in javascript, performance will be worse than this.
These numbers are approximate. I didn't run the benchmarks multiple times and I have a million things open on my machine. I doubt they'll be off by more than ~10% though.
Downloaded filesize increases by nearly 3x. Chipmunk-js is 170k, or 17k minified & gzipped. With emscripten the output is 300k, minified & gzipped to 49k. This is way bigger.
We can expose most of chipmunk directly to javascript. Unfortunately, we can't share vectors from inside the emscripten environment and outside of it - emscripten (obviously) inlines vectors inside its own heap & stack. In javascript, the best we can do is use objects in the JS heap. Our options are either removing vectors (as much as possible) from the API (cpBodySetPos(v) -> cpBodySetPos(x, y)), writing some javascript wrappers around everything to bridge between a javascript vector type and a C vector type or putting vectors in the emscripten heap (which would be faster than a JS bridge, but require that you match cpv() calls with cpvFree() or something. All options are kind of nasty.
Emscripten doesn't use the GC, so you can now leak memory if you don't cpSpaceFree(), etc.
As well as running faster, its easier to port code like this. Keeping chipmunkjs updated with the latest version of chipmunk should mostly just require a rebuild.