Compiling for the Web with WebAssembly

WebAssembly is a fast, portable, compact, cross-browser binary format for compilation to the Web. It allows new types of applications and heavy 3D games to run efficiently in browsers. We’ll describe what web assembly is, the problems it solves, the low level format and compilation tools available to try it out. In addition, the interfacing between compiled language modules and Javascript is explained.

What is WASM? A new binary format for executable code. An instruction set for a stack-based virtual machine. The result – code that runs really fast.

WASM comes from a community group including people from all the major vendors. The spec only went on to a formal working group to be finalised. It has been shipped in all the modern browsers.

WASM is designed to be a compilation target for other languages. So you can write something like C++ and run it in the browser.

Some history – asm.js and (P)NaCl came before, then lessons learned from there were taken forward into WASM.

WASM is not actually web! There’s nothing tying it to web browser. …and it’s not actually assembly either, it’s just a binary format.

WASM is not a replacement for JavaScript, it’s a complement to JavaScript. JS pulls in WASM modules and sends workloads off to it; and if you want to manipulate the DOM you still have to go through JavaScript.

What is it good for?

  • High performance code like video/CODECs, media editing, games.
  • Great for the huge amount of existing C/C++/Rust codebases out there – thousands of open source libraries that can be used in browser.
  • Existing C projects can be cross-compiled and shipped on the web from a single codebase. Autocad was put on the web this way.
  • Nodejs
  • Blockchain stuff in the browser

Very basic way to get started… install an SDK, then compile it with emscripten – you get two files, a .js file to load the module; and a .wasm file with your compiled code.

Every WASM binary is a module. WASM modules can only be accessed/used via their imports and exports. You can call it in JS:

module.exports.myfunction()

WASM and JS can be interleaved.

WASM is designed for efficient streaming, validation, compilation to native machine code.

Modules define functions, globals, imports, exports, memory requirements.

There are only 4 value types: 32 and 64 bit INT, and 32 and 64 bit FLOAT. Other types can be handled but they are not first class citizens.

Demos

  • Hourglass SVG which uses a C++ physics engine to determine how the grains of sand fall.
  • Live video processing – demo of an app that takes a live webcam feed and applies advanced filters on the fly.
  • New-generation video CODEC AV1, uses less bandwidth (big buck bunny is just 20megs)

Getting started

  • Go to webassembly.org
  • Install Emscripten
  • Run WASM modules in web workers, to offload heavy CPU work
  • Compile and link with `-O3`
  • Compile with `-Os` for the smallest file size

Debugging tips:

  • opening Chrome Dev Tools triggers an interpreter (stops JIT), so you can’t have them open if you are testing performance.
  • source map support coming in Chrome 71, debugging is currently pretty basic (console log)

Future of WASM, remembering it’s very much MVP at this point

  • SIMD instructions
  • fifth data type: ‘anyref’ for opaque object handles
  • host bindings (direct to DOM)
  • GC (garbage collection)