Where is WebAssembly now and what’s next?

This is the sixth part in a series on WebAssembly and what makes it fast. If you haven’t read the others, we recommend starting from the beginning.

On February 28, the four major browsers announced their consensus that the MVP of WebAssembly is complete. This provides a stable initial version that browsers can start shipping.

Personified logos of 4 major browsers high-fiving

This provides a stable core that browsers can ship. This core doesn’t contain all of the features that the community group is planning, but it does provide enough to make WebAssembly fast and usable.

With this, developers can start shipping WebAssembly code. For earlier versions of browsers, developers can send down an asm.js version of the code. Because asm.js is a subset of JavaScript, any JS engine can run it. With Emscripten, you can compile the same app to both WebAssembly and asm.js.

Even in the initial release, WebAssembly will be fast. But it should get even faster in the future, through a combination of fixes and new features.

Improving WebAssembly performance in browsers

Some speed improvements will come as browsers improve WebAssembly support in their engines. The browser vendors are working on these issues independently.

Faster function calls between JS and WebAssembly

Currently, calling a WebAssembly function in JS code is slower than it needs to be. That’s because it has to do something called “trampolining”. The JIT doesn’t know how to deal directly with WebAssembly, so it has to route the WebAssembly to something that does. This is a slow piece of code in the engine itself, which does setup to run the optimized WebAssembly code.

Person jumping from JS on to a trampoline setup function to get to WebAssembly

This can be up to 100x slower than it would be if the JIT knew how to handle it directly.

You won’t notice this overhead if you’re passing a single large task off to the WebAssembly module. But if you have lots of back-and-forth between WebAssembly and JS (as you do with smaller tasks), then this overhead is noticeable.

Faster load time

JITs have to manage the tradeoff between faster load times and faster execution times. If you spend more time compiling and optimizing ahead of time, that speeds up execution, but it slows down start up.

There’s a lot of ongoing work to balance up-front compilation (which ensures there is no jank once the code starts running) and the basic fact that most parts of the code won’t be run enough times to make optimization worth it.

Since WebAssembly doesn’t need to speculate what types will be used, the engines don’t have to worry about monitoring the types at runtime. This gives them more options, for example parallelizing compilation work with execution.

Plus, recent additions to the JavaScript API will allow streaming compilation of WebAssembly. This means that the engine can start compiling while bytes are still being downloaded.

In Firefox we’re working on a two-compiler system. One compiler will run ahead of time and do a pretty good job at optimizing the code. While that’s running code, another compiler will do a full optimization in the background. The fully-optimized version of the code will be swapped in when it’s ready.

Adding post-MVP features to the spec

One of the goals of WebAssembly is to specify in small chunks and test along the way, rather than designing everything up front.

This means there are lots of features that are expected, but haven’t been 100% thought-through yet. They will have to go through the specification process, which all of the browser vendors are active in.

These features are called future features. Here are just a few.

Working directly with the DOM

Currently, there’s no way to interact with the DOM. This means you can’t do something like element.innerHTML to update a node from WebAssembly.

Instead, you have to go through JS to set the value. This can mean passing a value back to the JavaScript caller. On the other hand, it can mean calling a JavaScript function from within WebAssembly—both JavaScript and WebAssembly functions can be used as imports in a WebAssembly module.

Person reaching around from WebAssembly through JS to get to the DOM

Either way, it is likely that going through JavaScript is slower than direct access would be. Some applications of WebAssembly may be held up until this is resolved.

Shared memory concurrency

One way to speed up code is to make it possible for different parts of the code to run at the same time, in parallel. This can sometimes backfire, though, since the overhead of communication between threads can take up more time than the task would have in the first place.

But if you can share memory between threads, it reduces this overhead. To do this, WebAssembly will use JavaScript’s new SharedArrayBuffer. Once that is in place in the browsers, the working group can start specifying how WebAssembly should work with them.

SIMD

If you read other posts or watch talks about WebAssembly, you may hear about SIMD support. The acronym stands for single instruction, multiple data. It’s another way of running things in parallel.

SIMD makes it possible to take a large data structure, like a vector of different numbers, and apply the same instruction to different parts at the same time. In this way, it can drastically speed up the kinds of complex computations you need for games or VR.

This is not too important for the average web app developer. But it is very important to developers working with multimedia, such as game developers.

Exception handling

Many code bases in languages like C++ use exceptions. However, exceptions aren’t yet specified as part of WebAssembly.

If you are compiling your code with Emscripten, it will emulate exception handling for some compiler optimization levels. This is pretty slow, though, so you may want to use the DISABLE_EXCEPTION_CATCHING flag to turn it off.

Once exceptions are handled natively in WebAssembly, this emulation won’t be necessary.

Other improvements—making things easier for developers

Some future features don’t affect performance, but will make it easier for developers to work with WebAssembly.

  • First-class source-level developer tools. Currently, debugging WebAssembly in the browser is like debugging raw assembly. Very few developers can mentally map their source code to assembly, though. We’re looking at how we can improve tooling support so that developers can debug their source code.
  • Garbage collection. If you can define your types ahead of time, you should be able to turn your code into WebAssembly. So code using something like TypeScript should be compilable to WebAssembly. The only hitch currently, though, is that WebAssembly doesn’t know how to interact with existing garbage collectors, like the one built in to the JS engine. The idea of this future feature is to give WebAssembly first-class access to the builtin GC with a set of low-level GC primitive types and operations.
  • ES6 Module integration. Browsers are currently adding support for loading JavaScript modules using the script tag. Once this feature is added, a tag like <script src=url type="module"> could work even if url points to a WebAssembly module.

Conclusion

WebAssembly is fast today, and with new features and improvements to the implementation in browsers, it should get even faster.

About Lin Clark

Lin is an engineer on the Mozilla Developer Relations team. She tinkers with JavaScript, WebAssembly, Rust, and Servo, and also draws code cartoons.

More articles by Lin Clark…


19 comments

  1. Marius Schulz

    A great introduction to WebAssembly. Thanks for writing this series, Lin! :)

    February 28th, 2017 at 10:13

    Reply

    1. Lin Clark

      Glad it was helpful!

      February 28th, 2017 at 13:59

      Reply

  2. Art Scott

    Aloha, Hi Lin.

    Used to be all we cared about in design space was s/t space and time

    Now design space is E/s/t Energy/space/time aware

    I look forward to the WA E/s/t story
    Hopefully the WA community will develop and tell the WA E story.

    Mahalo, Thanks Art

    February 28th, 2017 at 10:35

    Reply

  3. Anonymous

    Can the WebAssembly provide a higher level of security/resilience for DRM protection mechanisms?

    February 28th, 2017 at 19:23

    Reply

  4. Felix Almeida

    Thanks for putting these articles together. Well done!

    February 28th, 2017 at 21:48

    Reply

  5. Wink Saville

    Txs, very informative!

    February 28th, 2017 at 22:43

    Reply

  6. Hunan Rostomyan

    Thanks for the informative and beautiful series of articles.

    February 28th, 2017 at 23:36

    Reply

  7. AB

    Isn’t it possible that WASM becomes “JSVM”? This would give you an option to either compile JS for WASM or have it interpreted by JIT.

    I believe C# 4 and Lisp have many dynamic features but are also complied languages.

    March 1st, 2017 at 03:53

    Reply

  8. Felix Bernhardt

    Awesome series, I cannot wait to start using WebAssembly myself! All these new possibilities this implies are really exciting.

    Thanks a lot!

    March 1st, 2017 at 16:48

    Reply

  9. Phuong Nguyen

    Thanks for sharing this amazing news Lin :) , I can’t wait until it’s more stable to use it on my current web applications. Do you have a url to WebAssembly API or specification so I can get familiar a head ?

    March 2nd, 2017 at 07:09

    Reply

    1. Lin Clark

      Glad it was helpful!

      You can find out more about the spec and the API on the WebAssembly site. We also have more docs on Mozilla Developer Network.

      March 2nd, 2017 at 07:13

      Reply

  10. Marzio

    Hi Lin thanks for your serie of articles on web assembly. You make it look amazingly simple and intuitive.

    March 3rd, 2017 at 04:46

    Reply

  11. Chris

    Thank you for this series, very informative!

    As for WebAssembly in general, I’m really happy that the major browsers have reached a consensus on this. asm.js is a brilliant and creative idea, but it’s a band-aid nonetheless.

    WebAssembly is the clean solution that a lot of us were hoping for, and it’s only going to get better (i.e. faster and easier to use) from here.

    March 4th, 2017 at 03:40

    Reply

  12. Mehdi

    Just finished the series, very well written. Thanks!

    March 6th, 2017 at 04:50

    Reply

  13. Agrim Prasad

    A great series which gave a fairly detailed, yet intuitive introduction to WebAssembly. Looking forward to playing around with it soon.

    Thanks a lot Lin!

    March 6th, 2017 at 19:38

    Reply

  14. Anh Hoang

    Hi there,

    I did know about your code cartoon when started learning React, Flux, Redux, Graphql. And now, I intend to learn WebAssembly, Rust then I meet your code cartoon again. Is this destiny :)).

    Thanks a lot, Lin! You did save my career path !

    March 8th, 2017 at 08:59

    Reply

  15. Tomer

    I don’t usually comment on articles I read but this one is truly spectacular, thanks a lot.

    March 10th, 2017 at 07:31

    Reply

  16. Vladimir Z.

    Wow, just finished this great series!
    It was very interesting and clear, liked the cartoons.

    Learned a lot, thanks.

    March 10th, 2017 at 12:02

    Reply

  17. Kyle Hale

    Thank you! As a non web developer I managed to follow along pretty well, all thanks to your very clear explanations! Great job!

    March 28th, 2017 at 09:12

    Reply

Post Your Comment