More about asm.js powered physics

1
Official Construct Post
Ashley's avatar
Ashley
  • 6 Dec, 2013
  • 1,520 words
  • ~6-10 mins
  • 2,756 visits
  • 0 favourites

The latest beta r153 has a new option to allow you to select a new physics engine powered by asm.js. On Chrome and Firefox it's 2-3x faster than the old engine which was powered by Box2dWeb - fast enough to be close to native speeds, even on mobile! However, a couple of issues have caused us to only provide it as an option, instead of a new default. The reasons are a little involved, so this blog post aims to cover what it is, how it works, why it can be so much faster, and what the current drawbacks are.

What is asm.js?

Asm.js was invented by Mozilla to help web-based applications get closer to the performance of native apps, typically written in C or C++.

Traditionally, a native app would be written in a language like C++, and then the compiler generates CPU instructions from the code. The CPU runs the generated instructions directly, making it really fast (especially since C and C++ are designed to be high-performance languages).

Javascript traditionally has involved JIT (Just In Time) compilers generating CPU instructions dynamically. In other words, it starts off intepreting Javascript (which is slower), and then code which is used repeatedly gets compiled at runtime to CPU instructions. It's all pretty cool technology, but it has two drawbacks. Firstly, Javascript is not designed to be a high-performance language, like C and C++ are. This means it is difficult to generate instructions that are similar to what you'd get when compiling C or C++ - it has to be a lot more dynamic and general purpose, involving more work. It's theoretically possible it could be as fast, but achieving that is so difficult that in practice it's a few times slower. Secondly, Javascript is a garbage-collected language. This means it never explicitly frees memory. Every now and then the Javascript engine has to pause execution and figure out which bits of memory aren't used any more, and release them. This can make games "jank" (stutter as it has lots of short pauses). We'll come back to this one later to explain more how it affects physics.

So how do we solve these problems? Enter Emscripten, Mozilla's new compiler. This takes high-performance C and C++ code, and instead of directly generating CPU instructions, generates Javascript! It uses a very specific subset of javascript that is effectively a sequence of CPU instructions, but just so happens to be valid Javascript. This specific subset is what asm.js is: a particular simplified dialect of Javascript that is easy to optimise. Then Javascript engines which are optimised for asm.js can basically translate this Javascript straight in to the same lightning-fast CPU instructions you'd get from compiling the C and C++ traditionally. But it all happens in your browser! On top of that, it still works in old browsers which don't know about asm.js, since it's all still valid Javascript - it's just not as fast. Finally, like C and C++ there is no garbage collector used. This means it never creates any garbage, so it never needs to pause as it collects garbage from the code.

The new asm.js physics option is based around the original C++ Box2D engine compiled to asm.js using Emscripten.

If you'd like to learn even more about asm.js, John Resig (author of jQuery) wrote an excellent technical summary of it on his blog titled Asm.js: The Javascript Compile Target. (Note it's a touch out of date - the stable versions of both Firefox and Chrome now optimise for asm.js, whereas at the time it was written it was only a feature in Firefox Nightly.)

Garbage collection

The old physics engine is based on Box2DWeb. This is written in "typical" Javascript, and notably creates huge amounts of garbage. We pointed out in a previous blog post on writing low-garbage real-time javascipt that Box2DWeb can create hundreds of 'b2Vec2' objects (to store an X and Y co-ordinate) per frame. This creates loads of work for the garbage collector, and can make games prone to jank as the collector goes about its business cleaning up the thousands of allocations that keep coming.

It's possible to write Javascript that doesn't make many allocations by recycling objects, as described in that blog post. We've done a lot of work to optimise Construct 2's engine in that manner, ensuring that garbage collection work is absolutely minimal helping games to run as smoothly as possible. However using the Physics behavior would completely undo this, since it creates loads of garbage! This can then make your game liable to jank again despite all our work optimising Construct 2.

A very useful feature of asm.js is that it makes no allocations at all and never needs any garbage collection. If you switch to the asm.js physics engine, this eliminates the main source of garbage creation, and can eliminate much of the jankiness. That by itself is a very nice benefit, since now even games using physics create very little garbage overall.

Performance

Currently only Firefox and Chrome have specifically optimised for the type of Javascript that Emscripten produces. This can boost performance by 2-3x over the Box2DWeb engine, with the further bonus it creates no garbage!

Other browsers have Javascript engines which aren't yet specifically optimised for asm.js - notably Internet Explorer and Safari. However since it's still valid Javascript so it still works, and the browsers still compile it to CPU instructions dynamically for performance. It's not as fast as it could be, but our tests show it's not slower - if anything, a little faster. And in these browsers you still get the advantage that it creates no garbage at all, which helps make it run smoothly. Since asm.js code is easy to optimise, it seems likely these browsers will also add optimisations for asm.js code in future, enabling the same performance boost on those browsers. So the situation is likely to keep improving!

So even if your target platform is not Chrome or Firefox and asm.js physics don't appear to be much faster, there are still two good reasons to switch: it reduces garbage to ensure a smooth experience, and it could get a lot faster with future browser updates. However, there are two reasons you also might not want to switch.

Drawbacks

So if it's so much faster and better, why is it not simply the new default? The two main drawbacks are the following:

It does not support the 'Disable collisions' action. If you use it when using asm.js physics, it will simply have no effect and the objects will continue to collide. This is simply because the version of the asm.js physics engine we use didn't get this feature compiled in for some reason. We're going to investigate adding support for this, and hopefully can address it in a future release.

In iOS native apps, it can be slower. This is a tricky point. The Safari browser on iOS has a JIT compiler and can generate CPU instructions for Javascript to make it really fast. However when running Javascript in an iOS native app, like you get when using CocoonJS or PhoneGap, the JIT is not supported. This is a limitation in iOS. Since the app can't generate CPU instructions, it is always stuck in the slower interpreting mode. For many games this is still fast enough. However asm.js tends to generate large amounts of very simple Javascript. This can actually be slower than the non-asm.js version when stuck in interpreting mode (about 25% slower, according to a quick test). Note on CocoonJS you can take advantage of CocoonJS native physics, which is still very fast! However if you're using another wrapper like PhoneGap, you may want to stick to the old engine so you don't have to take a performance hit. Do remember though that the Safari browser itself is not affected and should still be at least as fast, and other platforms like Android are not affected - they can still use JIT in apps!

Conclusion

The new asm.js physics option is very compelling, and almost justifies being the new default, but we can't do that right now without breaking some existing games or slightly slowing down some iOS games. In short, the physics engine I'd recommend to use is as follows:

  • CocoonJS: CocoonJS native physics
  • Other iOS native app (e.g. PhoneGap): Box2D web physics
  • Anything using 'disable collisions': Box2D web physics
  • Otherwise: Box2D asm.js physics

This is especially cool on Android, where you can get huge performance boosts in browser-based games using Chrome or Firefox for Android, and also in native apps (where it still uses Chrome's V8 javascript engine with full JIT capability). Android devices often need to get all the performance improvements they can, and this is an excellent way to speed up physics games. Hopefully other browsers will keep improving, and perhaps in future iOS will even allow JIT from apps like Android can, solving that side of the problem. We'll also be investigating the 'disable collisions' feature for asm.js, and perhaps eventually we could set it as a new default for all Construct 2 games.

Subscribe

Get emailed when there are new posts!