What is WebAssembly?

WebAssembly 101 for web developers

Nebiyu Elias
8 min readFeb 5, 2023
WebAssembly logo

Introduction

If you’ve been in the web development ecosystem long enough you’ve probably heard about WebAssembly (or Wasm for short). It’s a nascent technology compared to the general history of the web. You know it’s a relatively new technology because most cool kids have not yet added the term to their resumes. Your initial thought about WebAssembly is that it’s fast and you would be correct. When we say WebAssembly is fast we are comparing it against something and that something is JavaScript. JavaScript is an unavoidable language in web development and it’s undoubtedly the King of the front-end world. But WebAssembly is not trying to dethrone JavaScript by any means. In fact, it’s expected people will use WebAssembly alongside JavaScript for the web.

WebAssembly in a nutshell

According to MDN’s WebAssembly pages:

WebAssembly is a new type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++, C# and Rust with a compilation target so that they can run on the web. It is also designed to run alongside JavaScript, allowing both to work together.

In a nutshell, it means:

  • You can run programming languages other than JavaScript in your browser. Your browser’s engine was only meant to run JavaScript code previously but now it can run code written in other languages such as C/C++, Rust, C#, and even Cobol.
  • WebAssembly is a low-level language similar to Assembly and it has a compact binary format. This will allow us to run code on the web at near-native speed.
  • It’s not meant to be a replacement for JavaScript on the web. It’s supposed to complement JavaScript. Using the WebAssembly JavaScript APIs, you can load WebAssembly modules into a JavaScript app and share functionality between the two. This allows you to take advantage of WebAssembly’s performance and power and JavaScript’s expressiveness and flexibility in the same apps, even if you don’t know how to write WebAssembly code.

WebAssembly is being developed as an open standard via the W3C WebAssembly Working Group and Community Group. This is like the ultimate geek club where all the major browser vendors send in their representatives and they geek out all things related to WebAssembly. This guarantees all major modern browsers will have support for WebAssembly by default.

Major browsers will have support for WebAssembly by default.
All the major browsers support WebAssembly

Why do we need WebAssembly anyways?

Now let’s take a bit of JavaScript history lesson to understand the need for WebAssembly.

JavaScript history on the History channel

As I have mentioned earlier when we say WebAssembly is fast we’re comparing it against JavaScript and we’re sort of implying JavaScript isn’t as fast as we wanted it to be. JavaScript is a high-level, flexible, and expressive language. Because of that, it was able to gain good adoption even though it has some quirks. But the ease of use costs performance. There’s always that tradeoff in programming when you do lots of abstraction.

JavaScript has some quirks
JavaScript has some quirks

When JavaScript was created back in 1995 it wasn’t fast. It was OK for JavaScript not to be fast because the web apps of the time were not that complicated. But slowly web apps started to get more complex and there was an inherent need to make JavaScript fast. Browser engines started adding something called a just-in-time (JIT) compiler to run JavaScript faster. As JavaScript was running, the JIT could see patterns and make the code run faster based on those patterns. I suggest you read this article by Lin Clark to understand JIT compilers.

This image was taken from https://hacks.mozilla.org/

Thanks to the introduction of JIT compilers, browsers are now able to run JavaScript code significantly faster. We have run into performance problems, however, when trying to use JavaScript for more intensive use cases like 3D games, Virtual and Augmented Reality, computer vision, image/video editing, and a number of other domains that demand native performance. WebAssembly is trying to bring that kind of performance to the web. With WebAssembly, hopefully, you will be able to use powerful video editing software like Adobe Premier Pro directly on the web.

What makes WebAssembly fast?

For you to be able to run JavaScript code, the browser’s JS engine has to turn your high-level instruction into machine code the computer understands. You and the machine talk in a different language. The browser’s JS engine will do a number of tasks to turn your high-level code into machine code:

The image is taken from https://hacks.mozilla.org/

Let’s try to understand the difference between WebAssembly and JavaScript by zooming in on those tasks:

Parsing

JavaScript source gets parsed into something called an Abstract Syntax Tree (AST). From there, the AST is converted to an intermediate representation called bytecode. In contrast, WebAssembly doesn’t need to go through this transformation because it is already an intermediate representation. It just needs to be decoded and validated to make sure there aren’t any errors in it. This is less time spent by the JS engine for WebAssembly code.

The image is taken from https://hacks.mozilla.org/

Compiling + optimizing

JavaScript is compiled during the execution of the code. Depending on what types are used at runtime, multiple versions of the same code may need to be compiled. But WebAssembly starts off much closer to machine code. The JS engine doesn’t have to spend a lot of time trying to optimize WebAssembly code as it’s already optimized.

The image is taken from https://hacks.mozilla.org/

Reoptimizing

Sometimes the JS engine has to throw out an optimized version of the code and retry it. This happens when assumptions that the JIT makes based on running code turn out to be incorrect. In WebAssembly, the JS engine doesn’t have to go through re-optimization cycles.

The image is taken from https://hacks.mozilla.org/

Executing

Executing code in WebAssembly is generally faster. Many of the optimizations that JITs make to JavaScript (such as type specialization) just aren’t necessary with WebAssembly.

The image is taken from https://hacks.mozilla.org/

Garbage collection

In JavaScript, the developer doesn’t have to worry about clearing out old variables from memory when they aren’t needed anymore. Instead, the JS engine does that automatically using something called a garbage collector.

This can be a problem if you want predictable performance, though. You don’t control when the garbage collector does its work, so it may come at an inconvenient time. Most browsers have gotten pretty good at scheduling it, but it’s still overhead that can get in the way of your code’s execution.

At least for now, WebAssembly does not support garbage collection at all. Memory is managed manually (as it is in languages like C and C++). While this can make programming more difficult for the developer, it does also make performance more consistent.

The image is taken from https://hacks.mozilla.org/

The key takeaways are:

  • WebAssembly doesn’t need to be parsed because it’s already in an intermediate format. It just needs to be decoded.
  • The JS engine doesn’t spend a lot of time trying to optimize WebAssembly code as it would with JavaScript.
  • In WebAssembly there is no re-optimization.
  • The execution step is faster.
  • Since you will be doing memory management yourself there’s no need for garbage collection by the JS engine.

In many cases, WebAssembly will outperform JavaScript. This is why it will be better to do performance-intensive tasks with WebAssembly.

A Practical Example

Now let’s look at a practical demo of WebAssembly. I have a C code that uses the OpenGL library to display a rotating cube. You can find the C source code here. First, let me run it on my local machine to show you it works. This means I have to compile the C code myself using:

gcc cube.c -lGL -lGLU -lglut

This compiles the code and creates a binary file called a.out and I can run the compiled binary using:

./a.out

When I do this, a new window is opened with the rotating cube:

A spinning cube example

Now, let’s use WebAssembly to run this same code on the browser. But we need to compile the C source code into WebAssembly. For that, we will use a tool called Emscripten. With Emscripten properly installed on your machine run the following command to compile the C code to WebAssembly:

emcc -s LEGACY_GL_EMULATION=1 -o index.html cube.c

The options we’ve passed in with the command are as follows:

  • -s LEGACY_GL_EMULATION=1 this enables support for a number of legacy desktop OpenGL 1.x features. This is related to OpenGL and you don’t have to be concerned about it.
  • -o index.html — Specifies that we want Emscripten to generate an HTML page to run our code in (and a filename to use), as well as the wasm module and the JavaScript "glue" code to compile and instantiate the wasm so it can be used in the web environment.

At this point in your source directory you should have:

  • The binary wasm module code (index.wasm)
  • A JavaScript file containing glue code to translate between the native C functions, and JavaScript/wasm (index.js)
  • An HTML file to load, compile, and instantiate your wasm code, and display its output in the browser (index.html)

Now to run the example we need to run the index.html file using something like LiveServer. You need to run your HTML file through an HTTP server (http://). If everything goes well, you should see the following in your browser:

A screenshot of the spinning cube on my web browser.

This is running directly in your web browser all thanks to WebAssembly.

Conclusion

This brings us to the end of the article. If you’ve reached this stage, thank you very much for your time. I have tried to explain what WebAssembly is and how it brings performance to the web. You have to know WebAssembly is not trying to replace JavaScript. Whenever you have a bottleneck in your JavaScript code you can surgically replace it with WebAssembly.

--

--

Nebiyu Elias

Software engineer by day, software engineer by night.