Skip to main content

Leveraging the power of WebAssembly in Web Apps

Introduction

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.

 

Problem with JavaScript

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.

Fig. 1.0 [Image credit: https://medium.com/@fhinkel
                            Fig. 1.0 [Image credit: https://medium.com/@fhinkel

 

Attempts to fix JS performance issues

In addition to execution engine enhancements, following actions are taken to overcome the performance issues in JS.  

  • Optimisers (e.g. prepack, jso)
  • Minifiers
  • Following rules & conventions

 Since JavaScript was the one and only programming language accepted by W3C at that time, different browser runtimes were produced to fill the vacuum.

 

History of browser runtimes

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.

  • ActiveX
  • Java Applets
  • Flash
  • Silverlight
  • Google NaCl

 

How WebAssembly solves these issues

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.

  • Small in size
    • It is already compiled & optimised by a compiler. As a result the Wasm artifact is quite concise so it can be quickly loaded by the client programme. This will ultimately improve the load time.
  • Less overhead
    • It doesn’t require a garbage collector. The language supports managing memory manually.
    • No parser required because Wasm code is closer to the machine code. So it is just decoded by the WebAssembly VM. But JavaScript VM has to generate the abstract syntax tree (AST) before preparing for the execution.
  • Fast execution
    • Wasm code does not require optimisations as it is already optimised by the compiler. So optimise/deoptimise the code in the runtime is not a requirement anymore. Which means there is no need for a profiler as well.
  • Low memory footprint
    • With the absence of the profiler and other runtime optimisation mechanisms, execution of a Wasm code requires relatively low amount of memory.

 

Use Cases for Wasm

There are no silver bullets. Each technology has its own sweet spot. The power of WebAssembly can be utilised well in below scenarios.

  • 3D & 2D Games
  • Audio/Video streaming
  • Fast audio/video codecs
  • Image recognition
  • Compression 
  • Crypto functions
  • Reusing existing C/C++ libraries on the web
  • Port existing apps as browser based applications (i.e. Autocad Web)  
  • Learn more

 

Architecture

WebAssembly is a virtual CPU which supports machine instructions closer to assembly instructions. But Wasm instructions are hardware/software independent (portable) & safe (sandboxed). 

Fig. 2.0
                                                                       Fig. 2.0

 

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.

 

Browser Support

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

Fig 3.0 https://caniuse.com/#search=webassembly
                               Fig 3.0 https://caniuse.com/#search=webassembly

 

 

Development with WebAssembly

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.

Fig 4
                                                                 Fig 4

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]

 

Write a simple programme in C

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.

 

Compiling a C programme as a WebAssembly target 

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. 

 

Fig 5.0
                                                Fig 5.0

 

 

WebAssembly Interoperability with JS

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

Fig 6.0
                                                     Fig 6.0

 

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.

 

 

Frameworks for WebAssembly

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

 

 

Future of WebAssembly

 

Currently the WebAssembly community is working on introducing a fantastic set of features, such as, 

  • Threading
  • Exception handling
  • Garbage collection and
  • ECMAScript module integration.

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

  • https://webassembly.org/
  • https://www.w3.org/2019/12/pressrelease-wasm-rec.html.en
  • https://marcoselvatici.github.io/WASM_tutorial/
  • https://blog.sessionstack.com/how-javascript-works-a-comparison-with-webassembly-why-in-certain-cases-its-better-to-use-it-d80945172d79
  • https://medium.com/hackernoon/webassembly-the-journey-what-is-wasm-caf9871108aa

LEAVE A COMMENT







POST COMMENTS


© 2021 Creative Software. All Rights Reserved | Privacy | Terms of Use