Friday, November 12, 2010

Now What?

For several months I've known that when I get home at night, I have tasks X and Y to do in Emscripten in order to move it forward. Last night, however, I took out the guitar instead. Suddenly, there is not much to do - basically the goals of the project have been achieved, Emscripten can compile things like the Bullet physics engine and run it on the web. As far as the core code-generating capabilities are concerned, Emscripten is pretty much complete.

So, what now?
  • There are some additional optimizations and enhancements that can be done, like nativizing structures or emulating multithreaded code.
  • There are various tooling improvements that can be done, like making it easier to glue together web code and compiled code.
  • Emscripten could be used in other ways, for example, it could be combined with something like Rubinius that generates LLVM code from Ruby, allowing running Ruby code on the web.
  • Various code cleanups and refactorings could be done.
I'm not in a rush to do any of these - none is urgent or essential. I guess I'll get around to them eventually, or perhaps someone else will.

Right now, I'm considering doing one or both of the following:
  • Return to my original goal, that of bringing Syntensity to the web. In other words, to compile a version of Syntensity using Emscripten. The time of 3D-environments-on-the-web is almost upon us, and when it is, we need to make sure that the main tools for it are open source and platform agnostic. Sadly, currently the main contenders are not such.
  • Some other side project, got at least two ideas in my head of things I'd like to hack up. They are very experimental and speculative though, so they may end up a waste of time. But if they succeed...

Tuesday, November 9, 2010

Bullet/WebGL Demo


Click on the screenshot for a live demo.

Monday, November 1, 2010

Emscripten 0.5!

Another Emscripten release has arrived, this time the focus was on building a large real-world library: Bullet Physics. For those unfamiliar with it, Bullet is an awesome physics library written in C++, which has been used in many places, including commercial games and movies.

Here is the demo for this release:

----------------------------------------------------------------------
Ran 168 tests in 1060.329s

OK

:P Just kidding, a real demo will follow. I'm working on something with Bullet and WebGL, but didn't want to delay the release for it.

About the work in this release: Bullet is much larger than other projects Emscripten was tested on before, and a large part of the work was to speed up the compiler. The result is that Emscripten now takes a reasonable amount of time - if it takes 10 minutes to build the Bullet C++ sources into LLVM bitcode, then it takes a similar amount of time to convert that into JavaScript using Emscripten (and it takes an even longer amount of time to run that through the Closure Compiler for additional optimization). So at this point there isn't much more reason to optimize for speed of compilation - it's in very good shape, fitting into the build process without slowing things down noticeably.

As expected, various small bugs were found while building Bullet, and a few additional tests were added to check for specific issues. There is also an automatic test for Bullet as a whole.

Overall, at this point Emscripten is capable of compiling large projects effectively; quite a lot of the original goals of this project have been achieved. Still lots of cool stuff left, though! More about plans for the near future in another blog post very soon.

Sunday, October 17, 2010

Emscripten 0.4!









The focus of this release was on making the generated code faster. As the chart shows, we went from being 100X slower than hand-optimized JavaScript code, to around 5X slower. You can see the difference in the raytrace demo, which has been updated to use all the current optimizations.

5X slower is still slower. It will be hard to do much better, though, without either better JS engine support, or much more clever code analysis. Both will hopefully happen over time. Meanwhile, 5X slower is not too terrible, and there are some advantages over hand-written code - we hardly use garbage collection, so no GC pauses. Also, the speed really depends on the code - the comparison in the chart above uses benchmarks for which we have comparable code in both C++ and JavaScript. But the most interesting uses of Emscripten are to convert code for which we don't have a JavaScript equivalent. Also worth mentioning is that it is perfectly possible to hand-optimize the crucial parts of the code that Emscripten generates.

Some technical details about the optimizations implemented in this release:
  • Use typed arrays, if available in the JS engine (thanks to pcwalton and njn for the idea)
  • Optimize after the relooper runs, removing unneeded code flow overhead
  • Nativize many more variables than before (i.e., move them off the emulated stack, and into native JS variables)
  • Optimized stack emulation
  • Inlining of various runtime code fragments
  • Integration with the Closure Compiler: We generate output that it is very good at optimizing (thanks to Anders Riggelsen for the idea)

Also added in this release is support for the brand-new LLVM 2.8. That is now the version being tested against.

Tuesday, October 5, 2010

Emscripten 0.3!

Demo for this release: Raytracing. It isn't very fast, since the focus hasn't been on code speed yet, but it does show that a ray tracer written in C++, using SDL, can be emscriptened and run on the web.

So, I ended up doing more in this release than I had intended, causing it to take longer than planned. But it was for the best. Major changes include:
  • Clang support: All tests now work in both llvm-gcc and Clang. The two produce somewhat different llvm bitcode, to the degree that different methods are needed with Clang, causing it to run 1/2 as fast as llvm-gcc code. That is mainly because llvm-gcc is more explicit with what it does, while Clang uses memcpy and such, with hardcoded C size values (4 bytes for an int, etc.).

    Emscripten therefore now supports optional 'C memory layout' (QUANTUM_SIZE in settings.js). For example, an array of ints of values 1,2,3 with that enabled is [1,0,0,0,2,0,0,0,3,0,0,0] (since each int is 4 bytes), and when it is disabled, [1,2,3]. The latter works fine with llvm-gcc-generated llvm bitcode. Note that things get even more complicated with structures here, which need to be aligned and so forth. Anyhow, after that effort Emscripten should now be able to support anything that C/C++ can throw at it.

  • Faster compilation speed: The original goal of the release. Compilation speed is 2-3 times faster now. Still lots of room for improvement, but it isn't a major nuisance like it was.

  • Proper memory management: A call stack is implemented, and static memory allocation (for global variables, etc.) is also possible. sbrk() is emulated as well, allowing dlmalloc, a popular malloc() implementation, to be emscriptened properly. In particular that lets you use a real malloc() in your emscriptened code.

  • Much better native flow regeneration (the 'relooper'): A major challenge of translating LLVM to JavaScript is to implement native flow structures - if, while, for, etc. LLVM bitcode only provides chunks of code (I call them 'labels', but that's not the right name) and branchings between then. So Emscripten needs to figure out from that low-level data the high-level code flow patterns. Native flow structures are extremely important for good performance of the generated code.

    The first relooper worked on most tests, but was slow and buggy. I wrote a new version almost from scratch, and it now properly processes all the test code. It isn't very fast, though, I didn't focus on that. For that reason it is off by default, which means that Emscripten will not generate native flow structures (instead it will emulate code flow using a switch in a loop, which is very slow - but trivial to generate).

  • The above-mentioned raytracing demo: For this, initial work was done on supporting SDL - just showing video data so far. The SDL Surface is implemented in JavaScript using a Canvas. I found this very amusing, to write C++ code with SDL, compile and run it natively using gcc, and be able to run that same unmodified code on the web through Emscripten ;)

  • Lots more tests: There are now 37 separate tests, from small LLVM features to high-level tests like the CubeScript engine, dlmalloc, and raytracing; each test is run through both Clang and llvm-gcc, and with relooping&optimization both on and off, for a total of 148 tests. This takes 7 minutes on my slow laptop, which is starting to be significant, but it's extremely important in a project like this.

Next goals include performance of the generated code - lots, lots of low-hanging fruit there - and compiling yet more real-world code.

Tuesday, September 21, 2010

Emscripten, Now With More Clang

Emscripten can now work with Clang. It turns out that the llvm bitcode that Clang generates is slightly different from that of llvm-gcc, which uncovered various minor bugs and missing elements in Emscripten (for example, the 'phi' command).

All the tests now pass both llvm-gcc and Clang, and with both optimization and relooping on (however, relooping has been weakened, due to some bugs that were discovered).

The benefits of allowing Clang to be used is that having two sources of LLVM bitcode is better than one - more chances to catch bugs (but even more important would be to add non-C/C++ sources of LLVM bitcode as well!). Another benefit is that Clang is simpler to build so it will allow more people to play with Emscripten.

The wiki has been updated with full instructions, so you can get Clang and try it out with Emscripten right now.

Saturday, September 11, 2010

CubeScript on the Web

Emscripten 0.2 is out, and here's a silly demo: the CubeScript engine from Sauerbraten, compiled from C++ to JavaScript, and running in a web page. Finally, you can use a script language on the web ;P

A few more details about the demo appear on that page. Other details about the 0.2 release are in the changelog.

After successfully compiling the CubeScript engine (which was mainly to see if Emscripten could do it - fixed a lot of bugs on the way), I think most C/C++ stuff should work (but there are probably a lot of minor corner cases left). The next steps are something like this:
  • Version 0.3: Optimize the compiler for speed. Right now compiling CubeScript, about 2,500 lines of code, takes a minute on my (slow) laptop. The goal is to compile large projects, so this needs to be much faster.
  • Version 0.4: Optimize the generated code for speed. Some radical solutions for making it faster are possible, but might take a lot of time, so maybe post-1.0. But some straightforward optimizations should be done in the near future.
  • Version 0.5: Tools and integration. Make it easy to build multi-file projects, and to connect the generated code to web JavaScript (calling functions both ways).
  • ???
  • 1.0!