What is WebAssembly and what makes it so powerful ?
Guillaume Cornet10 min read
At its beginning, the web gave us the possibility to view pages online that contained links to other pages, and that was basically it. All the applications, like text editor, were run on the desktop.
But since then, our way of using the web has significantly changed, and it is now used for many different purposes, from working simultaneously on a document to browsing social media or playing online games. The user experience is the main focus, and as a consequence, the demand in terms of performance is constantly increasing.
In this article, I will talk about the performances issues that JavaScript currently has to face and how WebAssembly is a potential solution to many of its issues.
The web, an incredibly efficient working tool
We tend nowadays to take the web for granted, forgetting that it has completely changed our way of working together.
I remember being in middle school and having to prepare a presentation with a friend. We were using Microsoft Office Powerpoint to do the slides.
The first step was to install Powerpoint on the new computer my parents had just bought. After inserting the 3 installation CDs, the setup was complete.
Then, I had to share the project with my friend. The problem was that I had the brand new Powerpoint 2007 version, so when he tried to open the project with his 2003 version, all the outline was broken.
I had to re-export the project in compatibility mode and re-send it to him, removing some slick animations in the process.
Finally, the day of the presentation finally came, so we opened the folder on the USB stick to get the presentation only to find…
So when google slides arrived, it opened a new perspective :
- Work instantly, using your internet connection and the URL to access the project.
- On a unique version, saved in real time on a server accessible by anyone with the right access.
- With no compatibility issue, since only one version of the application is available.
Once you make this realization for google slides, you start thinking: why do we still have desktop applications, like Photoshop? Wouldn’t it be much more convenient to be able to run it in the browser?
The naive solution to run Photoshop on the browser would be to re-code it entirely in JavaScript and you would lose a lot of functionalities because of JavaScript’s limited performance compared to the ones used to create Photoshop (which are PASCAL and 68k assembly for the curious).
Limited, you say ?
JavaScript was created in May 1995, as a result of a 10-days hackathon. Its initial goal was to add dynamic content to static pages: animate an element, change colors. The focus was then to allow developers to easily see the modifications that they made, which is why it is an interpreted language.
Because of the way it was conceived, they are inherent limitations to the language. To understand clearly what these limitations are I need to make a brief reminder of what the two main types of programming languages are and how they work.
The reason we need programming languages in the first place is that our computers only speak in bits sequence (0 & 1).
This is a CPU (Central Processing Units). It contains an Arithmetic and Logic Unit that does elementary operations (addition and subtraction) and a short term memory, the registers. When it receives a bit sequence, it is interpreted as an elementary instruction. For instance, this sequence would mean: add the content of R2 to the content of R1 and put the output into R3.
We humans do not have the ability to read easily the bits sequence, which is why we created programming languages.
There are two main types that I would like to describe :
- Compiled language
- Interpreted language
For compiled languages, the program is read in two key steps :
- First of all, a compiler transcribes the program written as a whole by the developer into a binary file.
- Then, this binary file is read and executed by the CPU.
This enables the compiler to make some optimization of the code before the execution so that it is faster and more efficient. The counterpart of it is that there is a compilation time every time the developer needs to execute the program after making a small modification.
For interpreted languages, the compilation and the execution are done simultaneously. During the execution, the interpreter reads the program line by line, compiles the line into binary and executes the binary before going to the next line.
It makes it easier to test small modification in your code because it saves the compilation time, but the consequence is that no global optimizations are made, and this impacts the execution time of the code.
JavaScript is an interpreted language and, as such, suffers from the performance limitations of this type of language. For a long time, this was not an issue because it did not require great performance, its purpose was essentially to provide dynamic elements to static pages.
Yet, 10 years ago, the browsers started to become competitive and wanted to provide a greater user experience than their concurrence, so they started to make optimizations in their JavaScript engine, introducing the Just-in-time compiler (the JIT).
While the code is being run, this JIT analyzes the code and tries to optimize the parts that are frequently called. This way, if the interpreter ever runs into the same part again, it will not translate it and use the pre-compiled part instead. It is a compromise between the two types of programming language.
JavaScript performance evolution graph
Source : Lin Clark, A cartoon intro to WebAssembly
These optimizations lead to a dramatic shift in JavaScript performance and allowed this language to be used for other purposes than its initial one, like running JavaScript code on the server side with node.js.
Yet, the performance of JavaScript is by nature still inferior to the performance of compiled languages like C.
You can see it easily on this codepen: https://codepen.io/jtiscione/pen/yxybjX.
Until very recently, if you wanted your application to be run on a browser then you had to code it in JavaScript and renounce to all the power of compiled languages.
But that was before WebAssembly.
WebAssembly
A small reminder: an assembly language is a programming language that describes the elementary operations that a machine has to make. It is specific to a type of processor, which means that there are many different assembly languages.
As explained on the official website, WebAssembly “is a binary instruction format for a stack-based virtual machine”. It was developed by the Mozilla foundation in 2016. Its goal is to become a complement to JavaScript.
WebAssembly is similar to ordinary assembly language, the main differences are :
- You do not write directly in WebAssembly, you compile it from higher-level languages.
- It is made to be executed directly from the browser.
- There is an extra level of abstraction on WebAssembly so that it can be executed on all types of processors.
There are at the moment many languages that can be compiled into WASM, including Rust, C/C++, C#/.Net, Java, Python, Elixir, Go.
What can you do practically with WebAssembly ?
I will show you in the next parts different applications of WebAssembly, but what you should remember is that it allows you to use the same base code for your desktop and browser applications.
Small code example
This is inspired by a conference of Google I/O 2018.
I have a C++ file that I am going to compile into WebAssembly using Emscripten. To get more information about the compiling process, you can check the official website of WebAssembly.
In this file, we are going to use the C math library in order to use mathematical functions to animate a blue circle in the DOM.
You can view the result here :
https://codepen.io/Gee2Cee/pen/eaNewE
First, I import the emscripten module, which allows me to define two js functions that interact with the DOM, drawCircle() and clearCanvas(). To do so, I need to make sure I wrap them with the EM_JS() function.
Then, I define a “real” C++ function. I have to prefix its definition by EMSCRIPTEN_KEEPALIVE so that the compiler does not ignore my function during the compiling process.
The “update()” function is the one that I will call in my html file at regular intervals so as to animate the DOM.
Once my C++ file is written, I can compile it using emscripten. I have two files as outputs, a pure .wasm binary file, and a .js file that contains all the necessary code to fetch the .wasm file and use it in my code.
Note: the .js file that is generated has over 1000 lines, yet you can easily write a simple js code yourself to import a wasm file and use one of its exported functions, as it is done here: https://codepen.io/SitePoint/pen/BrZeVZ.
Its applications
As you can see on the example above, WebAssembly is not made to replace JavaScript but instead they can work together. Here are some other examples of how you can use the benefits of compiled languages into js code.
-
You can export key functionalities of one of the many open-source C libraries into a js module, like the module bcrypt for node that realizes powerful calculation in order to encrypt any input like a password. This way, a JavaScript developer does not even have to know how to code in C - and does not even have to be aware that they are actually using a C library - to benefit from all of the power of a compiled language like C.
-
When it comes to performance on a browser application, WebAssembly can be particularly useful. Take for instance Figma: it is a useful tool for web designers and product owner that can instantly see all the designs of their application.
-
It also is a wonderful opportunity to take browser video games to the next level, you can check for instance the zen garden.
To summarize, JavaScript does its best with what it has been given, and it is quite satisfactory for the majority of its applications. Yet, as we have seen above, as soon as you need complex calculations, relying on JavaScript only can be disappointing if you want performances comparable to desktop applications, which is where WebAssembly comes in handy. Then you get the best of both worlds.
I hope that you are now convinced of the benefits of WebAssembly and that you will use it when needed in your next projects. And if you are worried about browser support, note that WebAssembly is supported on all of the modern browsers except IE 11.