Deploying Emscripten Compiled Pages — Emscripten 4.0.9-git (dev) documentation (original) (raw)

Emscripten compiled output can either be run directly in a JS shell from command line, or hosted on a web page. When hosting asm.js and WebAssembly compiled pages as .html for browsers to execute, Emscripten provides a default HTML shell file that serves as a launcher to run the code, simplified to get started with development. However when getting ready to release and host the content on a web site, a number of extra features and customizations are likely needed to polish the visitor experience. This guide highlights things to pay attention to when deploying sites to the public.

Build Files and Custom Shell

Emscripten build output consists of two essential parts: 1) the low level compiled code module and 2) the JavaScript runtime to interact with it. For example, when building with -o out.html, the compiled code is stored in a file out.wasm and the runtime lives in a file out.js. When targeting asm.js there exists an additional binary file out.mem that contains the static memory section of the compiled code. This part is embedded in the out.wasm file when targeting WebAssembly.

Additional build output files can also exist, depending on which features are used. If the Emscripten file packager is used, a binary out.data package is generated, along with an associated out.data.js loader file. Also Emscripten pthreads and Fetch APIs have their own associated Web Worker related script .js output files.

Developers can choose to output either to JavaScript or HTML. If outputting JavaScript (emcc -o out.js), the developer is expected to manually create the out.html main page in which the code is run in browsers. When targeting HTML with emcc -o out.html (the recommended build mode), Emscripten will generate the HTML shell file automatically. This shell file can be customized by using the emcc -o out.html --shell-file path/to/custom_shell.html linker directive. Copy the default minimal HTML shell file from Emscripten repository to your project tree to get a good starting template for a customized shell file.

The following sections offer tips for improving the site experience.

Optimizing Download Sizes

The biggest slowdown to speedy page loading is most often the need to download large amounts of asset data for the project, especially if the page is heavy on WebGL textures or geometry. Compiled code generally takes up more space than handwritten JavaScript, but machine code compresses efficiently. Therefore when hosting asm.js and WebAssembly, it is critical to ensure that all content is transferred using gzip compression, which all browsers and CDNs nowadays support built-in. Gzip compressing .wasm files give on average 60-75% size reductions compared to uncompressed ones, so it practically never makes sense to serve uncompressed files.

Optimizing Page Startup Times

In addition to downloading the page, other parts of the startup sequence can sometimes also be slow. Things to consider here are:

Providing a Quick Second Time Load

While the first run experience of visiting a page can take some time to finish all downloads, the second run experience of the page can be made much faster by making sure that the results of the first visit are cached by the browser.

Reserving Memory for Compiled Code

An inherent property of asm.js and WebAssembly applications is that they need a linear block of memory to represent the application heap. This is often the single largest memory allocation that an Emscripten compiled page does, and therefore is the one that is at the biggest risk of failing if the user’s system is low on memory.

Because this memory allocation needs to be contiguous, it can happen that the user’s browser process does have enough memory, but only the address space of the process is too fragmented, and there is not enough linear address space available to satisfy the allocation. To avoid this issue, the best practice is to allocate the WebAssembly.Memory object (ArrayBuffer for asm.js) up front at the top of the main page, before any other allocations or page script load actions are done. This ensures that the allocation has best chances to succeed. See the fields Module['buffer'] and Module['wasmMemory'] for more information.

Additionally, it is possible to opt in to content process isolation specifically for a web page that needs this kind of a large allocation. To utilize this machinery, specify the HTTP response header Large-Allocation: <MBytes> when serving the main html page. This support is currently implemented in Firefox 53.

Last, it is easy to accidentally cling to large unneeded blocks of memory after the page has loaded. For example, in WebAssembly, once the WebAssembly Module has been instantiated to a WebAssembly.Instance object, the original WebAssembly.Module object is no longer needed in memory, and it is best to clear all references to it so that the garbage collector can reclaim it, because the Module object can be dozens of megabytes in size. Similar, make sure that all XHRed files, asset data and large scripts are not referenced anymore when not used. Check out the browser’s memory profiling tool, and the about:memory page in Firefox to perform memory profiling to ensure that memory is not being wasted.

Robust Error Handling

To provide the best possible user experience, make sure that the different ways that the page can fail are taken into account, and good error reporting is provided to the user. In particular, proceed through the following checklist for best practices.

but instead, detect the actual errors:

if (!canvas.getContext('webgl2')) alert('Your browser does not support WebGL 2!'); // And look for webglcontextcreationerror here for an error reason.

This way the page will be future compatible once support for the particular feature later becomes available.

Prepare for The Web Environment

When planning a testing matrix before pushing a site live, the following items can be a good idea to review.

If you have good tips or suggestions to share, please help improve this guide by posting feedback to the Emscripten bug tracker or the emscripten-discuss mailing list.