Key Takeaways

  • WebAssembly’s first major version focused on the browser. WebAssembly is now expanding its focus beyond just the browser with a series of features designed to enable its vision of a portable binary format on many platforms, bringing great benefits in tooling and language-agnosticity.
  • A large number of non-browser runtimes have appeared with different areas of focus (performance, size, and more).
  • The Wasmtime runtime recently implemented the reference types proposal, allowing Wasm modules to properly interact with external host objects. This means better integration between a Wasm module and the outside world (DOM APIs when loaded inside a Webpage, or with a database API when instantiated on a server).
  • Thanks to the wasm-smith test case generator, hard-to-find bugs in the wasmparser Rust crate have been fixed
  • Next candidate features are type importsinterface typesmodule linking, and more.

WebAssembly recently became a World Wide Web Consortium recommendation and the fourth language to run natively in browsers, after HTML, CSS, and JavaScript. While WebAssembly’s first major version focused on the browser, WebAssembly is now focusing to non-browser environments to fulfill a variety of computational tasks, where sandboxing, portability or performance are essential. In this context, non-browser-based WebAssembly runtimes are being developed in miscellaneous languages, (Wasmtime and wasmer in Rust, GraalWasm in Java, Lucet in Rust, py-wasm in Python, swam in Scala, and more), with different areas of focus (e.g., performance for wasm3, blockchain applications for eos-vm, small footprint for wasm-micro-runtime). One challenge for these runtimes is to implement and experiment with the new batch of WebAssembly proposals that strive to fulfill WebAssembly’s vision outside the browser.

Although Wasmtime is implemented in Rust, the developers maintain APIs for embedding it within various other languages:

As Wasmtime recently implemented the reference types proposals, InfoQ interviewed Nick Fitzgerald, who implemented the feature, on his work involving WebAssembly and the next steps for WebAssembly and Wasmtime.

InfoQ: Can you tell us more about you?

Nick Fitzgerald: I work on the Wasmtime WebAssembly runtime, the Cranelift code generator, and various parts of the Rust and WebAssembly ecosystems.

Outside of work, I enjoy riding bikes (both for getting places and for doing fun tricks on my BMX), listening to hip-hop (I’ve had “CLONES” by Tierra Whack on repeat recently), and reading books (I just finished The Fifth Season by N.K. Jemisin and it was stunning!). I occasionally make algorithmic art and draw it with a pen plotter. Pen plotters are a precursor to modern printers—pretty much obsolete and only used by artists these days—that hold a pen in a little robot arm and draw vector graphics. I recently adopted a kitty cat from the local humane society; his name is Goomba. My pronouns are he/him.

InfoQ: How did you get involved with WebAssembly?

Fitzgerald: I stumbled into WebAssembly, but looking back this wasn’t really an accident: I was in the best position to stumble into it I could have been.

I used to work on the Firefox Developer Tools team at Mozilla, where I wrote and maintained our source map support. Source maps are a simple debugging information format for JavaScript. Minifiers and compile-to-JavaScript languages like TypeScript or Elm will emit them alongside their generated JavaScript code. The source maps allow debuggers and similar tools to translate locations in the generated code into locations in the sources that the developer originally authored. Source maps contain similar information as DWARF’s .debug_line section. With a source map, for example, the developer tools can show you “line 42, column 8 in my-module.js” rather than “line 1, column 643243982346519205631 in file minified-bundle.js.”

So here is the first connection: I was already working on tooling that helped people write code for the Web in a language that wasn’t JavaScript, should they choose to do so. WebAssembly also helps enable that, but now without compiling to JavaScript as an intermediate step. But all of this started before asm.js (a WebAssembly predecessor) was even a thing.

Anyways, source maps can contain a lot of information, so the format goes to great lengths to compact that information in as dense a representation as possible. Even so, source maps can get big, and decoding them can get quite expensive. When loading a Web page, the developer tools have to parse a source map before they let the page execute JavaScript, so that they can do things like set user-requested breakpoints in regions of top-level code that are only executed at start-up. This has to block: if it didn’t, and was asynchronous, then we have a race condition between whether we will finish parsing the source map in time to set the breakpoint, or whether that start up code will already finish executing before we get a chance to set our breakpoint. Because parsing source maps is on the critical path of reloading Web pages when the developer tools open, we care quite a bit about its performance.

Our library for parsing source maps was written in JavaScript. Over the years, we applied many optimizations and performance improvements to the library. We were bending over backward to avoid allocations and restructuring object layouts and function bodies so that Firefox’s JavaScript JIT compiler could better understand and optimize them. But we noticed that the more we optimized this code, the less idiomatic and less maintainable it became.

Fast forward a few years and WebAssembly has just started shipping on all major browsers and the Rust compiler has the brand-new wasm32-unknown-unknown compile target for compiling Rust programs into WebAssembly. I’m no longer on the Firefox Developer Tools team, but I had some free time over the 2017 winter holidays, and I wanted to try compiling some Rust to WebAssembly. Tom Tromey and I started brainstorming and bouncing ideas around, and we finally came up with the idea of replacing the core of the source map library with Rust compiled to WebAssembly and an architecture for doing that effectively. At the time, no one had been integrating Rust and Wasm into JavaScript libraries yet, and most uses of Wasm, in general, were monolithic C/C++ programs with tiny bits of JavaScript glue at the edges. People weren’t surgically replacing compute-bound kernels of JS code with small bits of Wasm like we were attempting, so we didn’t have a lot of direct examples to lean on.

When we finished rewriting the core of the source map library, we found that not only was the new code much faster, but it was still idiomatic. Rust didn’t force us to choose between runtime performance and clearly expressing our intent. For example, avoiding allocations in Rust (something that was a huge pain in the JavaScript codebase) is not only easy but natural thanks to Rust’s ownership and borrowing systems. To learn more about this project, check out my article Oxidizing Source Maps with Rust and Wasm on the Mozilla Hacks blog.

After the source map project, I was given the opportunity to work on Rust and WebAssembly full time at Mozilla. I led the Rust project’s WebAssembly working group, where we fleshed out the Rust and WebAssembly ecosystem and tooling. These days I’m focusing on the Wasmtime WebAssembly runtime for running Wasm outside the Web and the Cranelift code generator that Wasmtime uses under the covers.

#emerging technologies #webassembly #devops #architecture & design #development #article

Improving Webassembly and Its Tooling -- Q&A with Wasmtime’s Nick Fitzgerald
1.35 GEEK