WebAssembly(Wasm) is an official W3C open web standard for high performance web applications. It is the 4th language (Javascript, HTML & CSS) to run on browsers as recognised by the W3C. Webassembly is safe, compact, hardware independent, open and accepted by all the major browsers. It is not a language that developers may directly work on, but a portable compile target for other high level languages like C/C++ and Rust, which means, developers can compile their existing code into Webassembly if their compiler supports.
Wasm instructions are in very concise binary formats that can be loaded over the internet and executed by the Wasm virtual machine.
In this article we’ll discuss when webassembly shines and how to compile a C programme into Webassembly and run it on almost any browser.
JavaScript is not designed for performance in mind. It is designed for simplicity & multi paradigm. Optimisations are done by the execution engines such as V8.
When a JavaScript programme is being executed in a browser it has to pass multiple stages before actually being executed its instructions (fig. 1.0). Also there is a garbage collector to release allocated memory. So the programme is subjected to GC pauses as well.
Furthermore there is a profiler in action keeping statistics of executed code which contributes to relatively higher memory consumption.
The following diagram depicts how V8 engines executes JavaScript.
In addition to execution engine enhancements, following actions are taken to overcome the performance issues in JS.
Since JavaScript was the one and only programming language accepted by W3C at that time, different browser runtimes were produced to fill the vacuum.
Due to these issues and lack of flexibility different vendors tried to address those issues in their own way by providing different browser runtimes. But nothing was accepted by W3C as a web standard.
Now web assembly is an open standard. So it will be maintained carefully and continue for quite a while. On other hand, Wasm doesn’t require users to install additional runtimes on the browser. It will be available on web browsers by default. So the security and other critical updates are directly pushed by the browser vendor.
When it comes to performance, Wasm has a number of advantages.
There are no silver bullets. Each technology has its own sweet spot. The power of WebAssembly can be utilised well in below scenarios.
WebAssembly is a virtual CPU which supports machine instructions closer to assembly instructions. But Wasm instructions are hardware/software independent (portable) & safe (sandboxed).
With the current Wasm version there is no direct access to the web APIs such as DOM or Ajax. It should achieve this via JS. In the future WebAssembly might be given direct access to the web APIs.
All the major browsers support WebAssembly. Couple of Android browsers and Old Internet Explorer that has reached the end of life, don’t support Wasm. Since it is a W3C standard we can expect Wasm to be supported everywhere on the web
As I mentioned before we don’t programme directly in Wasm. Rather, developers choose a language where WebAssembly is supported as a compile target i.e. C/C++, Rust, Golang (experimental) and a WebAssembly toolchain i.e. Emscripten, LLVM, binaryen, wabt.
A basic WebAssembly development workflow is depicted below.
To demonstrate this I will write a function to calculate Fibonacci value for a given number and return.
Setting up the Toolchain
Below are the instructions to set up the Emscripten WebAssembly toolchain on Linux. For other platforms please refer to this.
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk/
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh --build=Release #[or add this to ~/bashrc]
For the sake of simplicity I am writing this programme in C.
hello.c
#include <stdio.h> |
|
#include <emscripten.h> |
|
int EMSCRIPTEN_KEEPALIVE fib(int n){ |
|
if(n == 0 || n == 1) |
|
return 1; |
|
else |
|
return fib(n - 1) + fib(n - 2); |
|
} |
[https://gist.github.com/kdkanishka/1b1cd8b05340e56b267c78e34fbc8bab]
Note: In the compilation process emscripten compiler ignores the unused methods. Since the fib() method is not used by any other function at the compile time, we need to “annotate” this function with EMSCRIPTEN_KEEPALIVE so the compiler doesn’t ignore the function.
emcc hello.c -o hello.html -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]'
If the programme compiles successfully, It should generate the WebAssembly programme as “hello.wasm”
Also it generates a JavaScript (hello.js) file which is the glue code or proxy for the fib() function. The project directory should look like this now.
In order to call the WebAssembly function from JavaScript, we should load the WebAssembly programme and create a wrapper to access that function. This can be done manually or we can use the generated gluecode (hello.js). In this example I am importing the generated glue code to keep the demo simple.
A function wrapper can be created for the fib function with the statement below.
var fibProxy = Module.cwrap("fib", "number", ["number"]); |
Now we can use the fibProxy object to invoke fib() function that we have already compiled to Wasm.
Let’s complete the programme...
We are going to create a wrapper for the fib() function and use it in below web page.
demo.html
<html> |
|
|
<script src="hello.js"></script> |
|
<script> |
|
var fibProxy = Module.cwrap("fib", "number", ["number"]); |
|
var input = document.getElementById("fibInput").value; |
|
var result = fibProxy(input); |
|
alert(result); |
|
} |
|
</script> |
|
<body> |
|
<label>Fib Calculator</label> |
|
<input id="fibInput" type="text"> |
|
<button onclick="calcFib()">Calculate Fib!</button> |
|
</body> |
|
</html> |
[https://gist.github.com/kdkanishka/cb9b46e69b8b10bc838662fc1f0312fa]
Now we have a complete programme. Let's run our demo web site.
Execute the following command in the project directory to create a small web server to serve our web page.
emrun --no_browser --port 8080
Now visit https://localhost:8080/demo.html
Output
This way we can write CPU intensive sections of our web applications in web assembly. It is also possible to access JavaScript functions from web assembly.
The best example is https://web.autocad.com/, the web version of AutoCad. They have lots of modeling and involve lots of calculations. So far they have had a desktop application. But with the rise of WebAssembly they could easily port their desktop application to the web.
Blazor is a framework which supports WebAssembly on either browser or the server and is developed by Microsoft. With Blazor developers can write both frontend and backend in C#.
They have achieved this by porting the mono runtime to WebAssembly.
Vugu is a golang based experimental framework.
TeaVM allows Java developers to write frontend applications in Java and compile into Wasm.
Asm-Dom allows writing single page applications in C++ and it provides access to virtual dom.
Here is a list of languages and frameworks which support WebAssembly.
https://github.com/appcypher/awesome-wasm-langs
Currently the WebAssembly community is working on introducing a fantastic set of features, such as,
For the updated set of features visit https://webassembly.org/docs/future-features/ .
What do you think about WebAssembly? Share your opinion as a comment.
References
LEAVE A COMMENT