Brief introduction to WebAssembly

WebAssembly

What is WebAssembly?

When I first heard about WebAssembly and read small article about it, I was convinced that it's just some kind of a runtime for low-level languages like C/C++/Rust designed to work inside the browser. But it turned out that it's just a part of the whole picture.

So what really is WebAssembly? Let's take a look at the definition from the official documentation:

"WebAssmebly is a binary instruction format for a stack-based virtual machine."

Ok, so this sentence do not clarify a lot for me, but it will be a good start point for further research. Let's try to understand it bit by bit. The first part of the definition is binary instruction format. After some research I found out that it's just bytecode format that is designed to be executed by virtual machine.

It's similar to Java, where Java code is compiled into specific bytecode and then executed by Java virtual machine. The same is with WebAssembly, it's compiled into bytecode and then executed by browser's virtual machine, next to JavaScript. From what it's compiled? It's compiled from any language that will have a support for it. Currently there are a lot of languages that can be compiled into WebAssembly, like C/C++, Rust, Go, Python, Ruby etc.

Second part of the definition - stack-based virtual machine. Stack is a data structure that stores elements in a LIFO manner (Last In First Out). It means that the last element pushed into the stack will be the first one to be popped out. This solution is great for VM, as it's only work with values that are on the top of the stack. It's good for reducing complexity of managing memory.

In WebAssembly we have instructions that are pushing and popping values to/from the stack. Let's take simple multiplication example:

i32.const 2 ;; push 2 to the stack i32.const 3 ;; push 3 to the stack i32.mul ;; pop 2 and 3 from the stack, multiply them and push result back to the stack call $log ;; pop result from the stack and print it ;; stack: 6

Of course compilers will optimize it, so in reality it will look little bit different. How it can look like? Assuming we have simple c++ code that will multiply two numbers:

#include <stdio.h> int main() { int test1 = 17; int test2 = 21; int sum = test1*test2; printf("sum: %d", sum); return 0; }

We can now run this code through WebAssembly explorer and see how it will look like in WebAssembly. The result is:

(module ;; [...] (import "env" "printf" (func $printf (param i32 i32) (result i32))) (func $main (; 1 ;) (result i32) (local $0 i32) (i32.store offset=4 (i32.const 0) (tee_local $0 (i32.sub (i32.load offset=4 (i32.const 0) ) (i32.const 16) ) ) ) (i32.store (get_local $0) (i32.const 357) ;; this is our result, there is no multiplication instruction anywhere ) (drop (call $printf (i32.const 16) (get_local $0) ) ) (i32.store offset=4 (i32.const 0) (i32.add (get_local $0) (i32.const 16) ) ) (i32.const 0) ) )

We can see that those two numbers were never declared, and we don't see any multiplication instruction either , only the result of it. This is because of previously mentioned optimization. The compiler knows that it's going to multiply two numbers, so it can just replace it with the result.

Now that we have some basic understanding of what WebAssembly is, let's take a look at how it was designed and what assumptions were made.

Design principles of WebAssembly

There are couple of assumptions that have to be made in order to design it properly (I've put them into my own words, if you want to read more about it, you can find it in design documentation)

  1. it should not trust the code that is going to be executed
  2. it should be able to support any language
  3. it should be as much cross-platform as possible
  4. it should be fast, and not only in execution, but also at startup

Let's take a look at each of them.

1. The first assumption was that it should not trust the code that is going to be executed.

Let's compare it to previously mentioned Java. If you want to open lets say a socket in Java, you just call

Socket socket = new Socket("localhost", 8080);

and you are done. In WebAssembly it can't be that easy. First of all, WebAssembly is meant to be executed in the browser, which is untrusted environment, so it has to be designed to be safe. So the first assumption was to not trust the code that is going to be executed.

2. The second assumption was that it should be able to support any language.

This was more like a wish, because it's impossible to support all languages, it has to be done by the community. But if they will give them a proper instructions set, then it's just a matter of time when it will be fully supported.

3. The third assumption was that it should be as much cross-platform as possible.

It means that it should be able to run on any platform, like Windows, Linux, Mac, Android, iOS etc. It's not that easy, because each platform has it's own instruction set, so it has to be designed in a way that it will be able to run on any platform.

4. The fourth assumption was that it should be fast, both in execution and startup.

It's not that easy, because it has to be compiled to binary format, which is not that easy to parse. So it has to be designed in a way that it will be fast to parse and execute.

Use cases for WebAssembly

After digging deeper I found out that use cases of WebAssembly can be separated into two main categories:

  1. inside the browser

    1. almost native performance for running low-level languages
    2. music and video processing
    3. CAD and 3D modeling
    4. games
    5. in tools like figma, photoshop, etc.
  2. outside the browser

    1. cloud computing
    2. IoT devices
    3. server-side applications
    4. desktop applications
    5. mobile applications

More use cases can be found in the official documentation.

Summary

Is WebAssembly going to revolutionize the web? It's hard to say. It's still in development and it's difficult to predict what will happen with this technology in the future. But if the work will be continued, then it can be a game changer. Let's think of a OS that you just have to install, and all applications that you desire will be available in the browser. No more insecure applications on Windows, no more viruses, no more problems with installing and uninstalling applications. Just install the OS, open the browser and you are ready to go. That's the future that I would like to see. Cheers!

Valuable resources

  1. WebAssembly introduction
  2. WebAssembly design documentation
  3. WebAssembly explorer
  4. WebAssembly use cases