WebAssembly: Easy explanation with code example
Why WebAssembly?
Background: Web and JavaScript
Undoubtedly, web is highly portable and machine-agnostic, making it a truly universal platform.
Web is the only one true universal platform. ☝️
JavaScript (JS) is the default language of web-development. It has native support of many web APIs like DOM, Fetch, Web-sockets, Storage etc., and as browsers are becoming more powerful, we are writing more complex clients using JavaScript (or languages that transpile to JS).
However JavaScript has some limitations when it comes to running big complex applications on browser.
Limitations of JavaScript
- Not good for CPU-intensive tasks
- JS is text based and not binary-based, more download bytes and hence more startup time.
- JS interpretation and JIT-optimization consumes CPU and thus battery life
- Need to rewrite already existing non-JS libraries, modules and apps in JS
Web development community is trying to overcome these limitations and opening up web to other programming languages by bringing a new entrant in web-development called WebAssembly.
On 5th Dec. 2019, WebAssembly became the fourth language standard along with HTML, CSS, and JavaScript to run natively in browsers.
Web Assembly (WASM)
WebAssembly is a type of binary-code that can be run in modern web browsers, it enables us to write code in multiple languages and run it at near-native speed on the web.
Features of WASM
- WASM is a low-level language not to be written by humans but compilation target for other languages like C/C++, Rust, AssemblyScript etc.
- WASM is binary-format and thus less download bytes (there is an equivalent text-format for humans too, called WAT).
- Unlike JS, WASM binary is decoded and compiled to machine code without need of any optimization, as it is already optimized during generation of WASM binary
When to use WebAssembly?
- CPU intensive tasks like maths in Games or other graphic apps, Image and Video manipulation etc.
- Running old C/C++ libraries and apps on web providing portability and eliminating need to re-write C/C++ code into JS.
- To eliminate the need of making native apps and various compilation targets as single WASM compilation would enable it to run on different processors through web browsers.
WASM is here not to replace JS but work alongside it. JavaScript has already good collection of Native web APIs, WASM is here to assist with the heavy lifting.
Note:
Modern JavaScript engines are very fast and highly optimize our JS code, so WASM bundle size and execution time might not be very advantageous for simple tasks.
I am not doing any benchmarking in this article but would refer to resources at the bottom of this article for benchmarking links.
How to use WASM (deep-dive 🤿)
Let’s follow above steps to create a function in C to calculate factorial of a number and consume it in JS as WASM.
We can compile above C function into WASM using Emscripten:
emcc factorial.c -s WASM=1 -o factorial.html
It will generate factorial.wasm
binary file along with html-js glue code. A list of output targets is referenced here.
Its equivalent human readable textual format WAT is shown below.
There are various ways one can send the binary data of WASM to web-client and we can use javascript’s WebAssembly
API to compile the binary data to create WASM Module and later instantiate this Module to access exported functions.
The most efficient, optimized way to load WASM code is to use WebAssembly.instantiateStreaming()
function that compiles and instantiates a WebAssembly module directly from a streamed underlying source.
Following is the example code of using instantiateStreaming
for consuming previously generated factorial.wasm
file, which can be served by our server and can be called by our web-client on demand. We can then instantiate received WASM module using following JS code and can access the exported factorial
function.
To get a quick feel of the explained steps without the pain-staking setups, WASM fiddle can be used.
Browser support
All modern browsers (Chrome, Firefox, Safari, Edge) support it. Click here to see the latest support stats.
IE does not support WASM. If there is a need to use C/C++ code in IE, we can compile it to asm.js (a subset of JS) using Emscripten.
Future
Support for thread management and garbage collection is being implemented. This will make WebAssembly more suitable as a compilation target for languages like Java, C#, Go.