Hi all,
I'd like to raise some awareness about the awesome --separate-asm linker flag that Alon added some time ago to Emscripten, in version 1.34.8 (9/9/2015). What it does is it splits out the generated output files so that instead of one large .js file that contains all the code, two files foo.js and foo.asm.js will be emitted. The file foo.js will contain the Emscripten preamble, runtime and all the handwritten JS functions (--js-library code) and the --pre-js and --post-js content, whereas the foo.asm.js will only contain the big asm.js module that it assigns to Module.asm.
This has multiple benefits:
- Often the single monolithic output is too large to handle in browser debugger and most text editors that do syntax highlighting. Often the debugging activities occur on the bridge layer where the compiled code talks to the browser, so it is the handwritten JS code that is of most interest. Separating these out to two files makes it easier to navigate the code and set breakpoints in browsers to the JS runtime itself.
- Looking towards WebAssembly, if you intend to later ship both a wasm version and an asm.js version of a single page for backwards compatibility, we'll try to make this easy for you by creating a single .html file that loads .wasm if supported, and if not, it'll fall back to the .asm.js version. This will utilize the --separate-asm path.
- Just recently, we had a big memory improvement land in Firefox (currently in Nightly branch, looking at Firefox 49 release on 2016-09-13) where we are able to recognize the JS script only containing asm.js content, in which case we handle the script memory of that file much more efficiently. JavaScript has from an Emscripten developer's viewpoint a rather exotic feature that requires browsers to retain the JS file contents around, e.g. because one can print the function bodies to a string. For asm.js modules, this is not really needed, so we have pushed this to a cold path by compressing the asm.js script data in memory. This can save 50MB+ of memory on large asm.js codebases. This improvement is something that is asm.js only, WebAssembly will by design avoid this source of memory consumption.
- Also noteworthy is that when you are building with -s USE_PTHREADS=2 or -s PRECISE_F32=2 flags to enable backwards compatibility for non-SharedArrayBuffer/Math.fround capable browsers, --separate-asm is already implied, because the backwards compatibility architecture on these two features requires this.
For these reasons, we definitely recommend enabling --separate-asm when building if possible. There are some drawbacks to this though, which might make it undesirable for some cases:
- two files is more than one, which might be inconvenient.
- there is a small amount of extra complexity that needs to be taken into account when loading. The file foo.asm.js needs to be loaded up before the file foo.js, since the asm.js module needs to be available to run the main file. If you are outputting straight to html with -o foo.html, then Emscripten will generate a proper loader for you, which XHRs the data in in the proper order. If you are outputting -o foo.js however, it will still generate the foo.js and foo.asm.js, but you'll need to manage the required XHR sequence by yourself on your site .html page. If this is not run in correct order, you'll likely see the JS exception "Module['asm'] is not a function" be thrown in the page console.
Hope that is useful!
Jukka