At the BrazilJS Conf my colleague Willian Silva and I will talk about our findings measuring the performance of an implementation of John Conway’s Game of Life with three approaches: Web assembly, Vanilla JS and Web workers. Our assumption was that the performance would rank as follows:

  1. Web workers
  2. Web assembly
  3. VanillaJS

Our tests are available in this repo on github, but before showing our results, we want to quickly introduce the concepts behind each approach.

Web Assembly

Webassembly (wasm) is a binary format code that allows the user to run programs written in languages like C, C++ and Rust with near native performance on a browser. The interesting thing is that webassembly has been created not to be an alternative to Javascript but to work with it, providing developers the same performance of compiled languages and the flexibility of Javascript at the same time.

Web Workers

As defined in the MDN Documentation, Web worker is a simple means for web content to run scripts in background threads. This allows the user to improve performance by running different parts of the computation in parallel.

The Project

We wanted to understand how to include a webassembly program in a js project and measure the performance of it compared to the other two approaches.

The Game of Life seemed like a good benchmark for measuring performance since it would require a lot of computation to generate the next state, particularly because of each state’s big size matrix.

The structure of the project was written in plain Javascript, using webpack for compilation. The game matrix is rendered using a canvas. Since the rendering did not differ between the versions of the algorithm, we considered it not relevant to the performance comparison.

In the first iteration, we implemented the algorithm to calculate the next state using Vanilla JS.

We tried to use as many separate functions as possible in this implementation and it revealed itself to be pretty fast.

Vanilla JS performance

Vanilla JS performance

After that we rewrote the same logic in C. To compile the program we used emscripten: a useful tool that wraps a compiled C program into a Javascript module, while providing several methods to manage and access webassembly memory.

The initial implementation of the game using webassembly was not as fast as the plain Js version. We realized that this was mainly due to the overhead of reading and writing a big matrix from and to webassembly memory by javascript.

We managed to reduce this memory access by a single read of the next state matrix. Anyway the performance results were still on the side of Vanilla JS.

After further investigations we came to the conclusion that calling webassembly functions from javascript code is still a not fast enough process. This is more prominent on Spyder Monkey JIT: since it doesn’t know yet how to directly deal with webassembly (it’s still an MVP), it has to route the call to a piece of code that knows how to run wasm. The problem is that this call can be up to 100% slower than direct access. This overhead becomes a bottleneck when js calls the webassembly function repeatedly (like in our state calculation). That’s why the C implementation performs worse.

For now, the best way to take advantage of webassembly is to use it for big calculations, which JS requires only a few times.

WebAssembly performance

WebAssembly performance

In the end, we developed a version of the same JS algorithm that uses web workers to split the calculation in multiple parallel threads. This solution was the best one in terms of performance, as expected.

Web Workers performance

Web Workers performance

Conclusion

Webassembly is a very exciting technology that can improve the speed of the critical path of web applications in near future. It’s still experimental, but all majors browsers vendors have plans to release it in the following versions. You can play with the MVP version on Chrome 59 and Firefox 54.

wasm-working-project

Elia Maino and Willian Silva working on the webassembly project at foodora HQ.

Posted by on 22 Aug 2017

Software engineer

Leave a Reply