The need for speed: Emscripten and Chipmunk

Official forum for the Chipmunk2D Physics Library.
Post Reply
josephg
Posts: 29
Joined: Sat Dec 24, 2011 4:54 am
Contact:

The need for speed: Emscripten and Chipmunk

Post by josephg »

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:

Code: Select all

Time(a) =  1451.45 ms (benchmark - SimpleTerrainCircles_1000)
The same benchmarks running with chipmunkjs in node 0.10.12 (v8: 3.14.5.9):

Code: Select all

$ node bench.js 
SimpleTerrainCircles 1000
Run 1: 22426
Run 2: 21808
(ie, 21 seconds, 15x slower)

Using v8 head (v8: 3.19.18.5):

Code: Select all

$ ../v8/out/native/d8 bench.js
SimpleTerrainCircles 1000
Run 1: 11248
Run 2: 12930
(8x slower)

Emscripten (-O2 -DNDEBUG), v8: 3.19.18.5 in Chrome Canary:

Code: Select all

Time(a) =  3967.12 ms (benchmark - SimpleTerrainCircles_1000) 
(2.7x slower)

In Firefox 22 (which has asmjs support) (Firefox nightly (25a) has about the same performance):

Code: Select all

Time(a) =  2044.10 ms (benchmark - SimpleTerrainCircles_1000)
(1.4x slower!!!)

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: https://gist.github.com/josephg/5892575

- 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.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: The need for speed: Emscripten and Chipmunk

Post by slembcke »

Ooh. That's pretty good. I've been meaning to try that out since going to the Firefox talk at GDC about the asm.js stuff. I did get the impression that it's a little difficult to mix the "C" and javascript code though since it's compiled down to some very low level JS code. I talked to one of the Emscripten guys briefly and he also said that you needed to make wrapper functions to call into the Emscripten code to do type checking and conversions, but that there were tools to automate that.

The code size is much better than I expected. A couple years ago I had tried Emscripten on some trivial stuff and it produced *huge* JS files since it included JS compiled versions of a lot of the C std lib. I wanna say a "hello world" program was like almost a megabyte or something ridiculous, but I don't really remember. I guess it's gotten better at linking them or something? 49k is pretty tiny compared to the size of images.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
josephg
Posts: 29
Joined: Sat Dec 24, 2011 4:54 am
Contact:

Re: The need for speed: Emscripten and Chipmunk

Post by josephg »

49k only once its gzipped. The chipmunk static library shouldn't be that much bigger if you compress it. I think its smaller now because they added dead code removal - so most of the standard library can be removed.

In comparison, the direct JS port of your C code compresses down to 17k.

The code emscripten generates is still pretty bad too. This is cpSpaceSetGravity (newlines & comments added by me):

Code: Select all

// c contains a uint32 array view on main memory.
function bU(a,b){ // a is space*, b is a stack pointer to the new gravity vector
  a=a|0;
  b=b|0;
  var d=0,e=0;
  d=i; // Save the current stack pointer (i)
  e=b;
  b=i;

  i=i+16|0; // stackptr += sizeof(cpVect);
  c[b>>2]=c[e>>2]; // Copy the new gravity vector onto the local stack.
  c[b+4>>2]=c[e+4>>2];
  c[b+8>>2]=c[e+8>>2];
  c[b+12>>2]=c[e+12>>2];

  e=a+8|0; // void* e = (space + offset_of(space->gravity))
  a=b;
  c[e>>2]=c[a>>2]; // Copy from the stack to space->gravity
  c[e+4>>2]=c[a+4>>2];
  c[e+8>>2]=c[a+8>>2];
  c[e+12>>2]=c[a+12>>2];

  i=d; // Restore the stack pointer
  return;
}
This is all thats actually needed:

Code: Select all

function cpSpaceSetGravity(a,b){
  a=a|0;
  b=b|0;
  HEAP64[a+8>>3] = HEAP64[b>>3];
  HEAP64[a+16>>3] = HEAP64[b+8>>3];
}
... Although, I worry that my hand tuned minimal javascript might not actually perform as well. But if it did, you could probably do a much better source-to-source translation from the C code to asmjs without using llvm. (I'm not sure if I can be bothered, but its still interesting).

And yeah, exposing a decent API in JS is also a pain, and also not included in that code bundle.
josephg
Posts: 29
Joined: Sat Dec 24, 2011 4:54 am
Contact:

Re: The need for speed: Emscripten and Chipmunk

Post by josephg »

If anyone's following along, for curiosity's sake I played with some hand written asmjs:
http://josephg.com/chipmunk-in-asm-js
https://gist.github.com/josephg/6111405

Its kinda fun writing in an asm-like language, though I'm not going to give this treatment to all of chipmunk.
Post Reply

Who is online

Users browsing this forum: No registered users and 14 guests