You’ve probably heard it claimed that WebAssembly is fast. But what exactly does that mean and what is it? In this post, we’ll dive into those questions and also get a glimpse into the future.
I think it’s important to start with some clarification: statements made regarding performance are always relative, and in the case of WebAssembly there is a lot of nuance that is often difficult to fully see and so this post doesn’t read as one continued rambling of “well, actually”, not everything is elaborated on. Keep that in mind! Just remember that WebAssembly is exciting, but it’s not a silver bullet.
WebAssembly (aka Wasm) is an efficient, safe, low-level bytecode for the Web. That sounds nice, but let’s break this down to truly understand what we mean.
When most people talk about WebAssembly, they talk about its potential performance benefits at runtime because it’s compiled to efficient machine code by your browser. However, runtime performance isn’t the only thing it’s efficient at.
WebAssembly was designed from the ground up to have a very compact, binary file format, so it can be fast to download, but more importantly it can be compiled to machine code while it’s being downloaded. This is called Streaming Compilation.
The Web has enjoyed tremendous success in advancing what a browser can do, while still protecting us from malicious intent. WebAssembly continues that precedent.
This is might seem fairly limiting — and it is — but it was very important to start off with a proven, secure foundation.
WebAssembly also provides additional safety for languages like C/C++. The most common example is the good old stack smashing/overflow exploit, where a buffer is overrun and executable code is injected. Because of the way WebAssembly works, that exploit isn’t even possible! You can still overrun buffers — this is allowed from the C++ specification — but there is no concept of executable memory so injecting code would be pointless.
WebAssembly is intended to be compilation target, not something you’d normally write by hand — but you can. You’ll write code in a human-readable programming language (like C++ or Rust) and compile it down to the machine-readable binary object code aka bytecode.
Some C/C++ code compiled to WebAssembly bytecode
Bytecode is similar to your native computer’s machine code, except it’s designed for a virtual machine instead of a real one. This makes it very low-level, which enables performance optimizations, but still portable; you don’t have to worry about which CPU (x64, ARM, etc) your users have. Browsers provide a built-in WebAssembly virtual machine, but ironically, WebAssembly isn’t just for the Web — more on this later!
You might be familiar with other bytecode formats like the .NET CIL (CLR) or Java bytecode (JVM). It’s natural to wonder why browser vendors didn’t just add support for one of these (or another) instead. The exact reasons are a bit complex and technical, but ultimately other virtual machines had incompatible goals. As one example, WebAssembly files can be verified and compiled by the virtual machine in a single pass, unlike most contenders, allowing streaming compilation.
There are numerous other reasons, but even if they had chosen one of the existing bytecode formats, it wouldn’t have allowed you to run existing binaries as-is because they don’t sandbox the operating system enough. For example, the JVM provides unrestricted file system access with APIs like
java.io.* which is a big no-no for the Web. Instead, the goal is to use the Web’s existing APIs and sandbox model.
WebAssembly v1.0 aka MVP
In my opinion, the biggest reason WebAssembly hasn’t taken off like a rocket is that it’s being designed incrementally, so certain features are “missing” for broad appeal. The initial 1.0 version, dubbed the MVP, is best suited for languages like C/C++ and Rust and even with them, not all use cases.
This was a wise, intentional choice because standards notoriously take forever to finalize. It also allows the standards body take in feedback and refine their goals incrementally from real-world usage. It’s very hard, usually impossible, to remove something from the Web once it’s shipped, so making the right choices the first time is paramount.
Here is where things get a bit awkward. Since WebAssembly is a compilation target, not something you write by hand, how exactly you “get started” depends on the higher-level language you’re going to write and ultimately compile.
If you’re into Rust, you’re quite in luck because the Rust core team has really doubled down on WebAssembly. There’s even a dedicated Working Group to improve the experience. You’ll want to check out their Rust+Wasm book.
Other languages have early support for WebAssembly too, like Go. Expect these to improve significantly in the coming years.
Neither Web nor Assembly
Most of this post (and the Web in general) assumes that when we’re talking about WebAssembly, we’re talking about it running it inside of a browser. However, pretty ironically I must say, WebAssembly’s name is a misnomer. It’s not an assembly language, it’s a bytecode — though there is a textual “assembly” language to represent the binary bytecode.
More importantly, it’s not just for the Web!
The WebAssembly designers knew it was unprecedented for the major tech companies of the world to get together and design a completely free, standardized instruction set. They made a conscious effort to make it generic, not fundamentally tied to browsers.
We’re just beginning to see how it’s used outside of the browser, but already there are some exciting projects.
Nebulet, operating system microkernel that runs only WebAssembly
wasmjit, WebAssembly running in the kernel/ring-0
Wasmer, universal binary platform
WebAssembly can be used today in all modern browsers (i.e. not IE11), and in performance critical, fairly algorithmic use cases it’s already providing huge performance benefits for real world use cases. But in particular I’m most excited for the post-MVP future of WebAssembly and what it will mean for not just for the Web, but everywhere.
I also highly recommend checking out the Awesome Wasm repo which has links to all things WebAssembly.