WebAssembly cut Figma’s load time by 3x
A WebAssembly case study
WebAssembly was just released this past March but has already generated a lot of excitement in the web community. It’s a new binary format for machine code that was specifically designed with browsers in mind. Because apps compiled to WebAssembly can run as fast as native apps, it has the potential to change the way software is written on the web.
Many people have started experimenting with toy WebAssembly projects on the side, but it’s hard to tell what the real-world performance gains will be unless you have a large compatible code base for comparison. Because our product is written in C++, which can easily be compiled into WebAssembly, Figma is a perfect demonstration of this new format’s power. If you haven’t used Figma before, it’s a browser-based interface design tool with a powerful 2D WebGL rendering engine that supports very large documents.
We thought our findings would be useful to the web community as an example of WebAssembly’s impact. Spoiler: it’s much faster.
Overview of WebAssembly
WebAssembly allows developers to create desktop-quality experiences on the web without compromising on performance. All major browsers are adding support for it and devoting significant resources to making it as fast as possible.
If you’re interested in learning more about WebAssembly, I can recommend both Lin Clark’s high-level intro presentation and a low-level post by Rasmus Andersson, a designer and engineer who works at Figma, which describes the WebAssembly format in excellent detail. The official docs have a getting started guide if you’d like to play around with it yourself.
WebAssembly and Figma
The biggest benefit we saw from using WebAssembly at Figma was faster load time. This isn’t surprising since one of WebAssembly’s primary goals is to reduce load time. When we measure load time at Figma we include the time to initialize our app, download the design file, and render the whole design for the first time.
As you can see, our load time improved by more than 3x after we switched to WebAssembly regardless of document size. This is a huge improvement for our users, who often create very large design documents and frequently switch between them.
An additional load time benefit of WebAssembly that isn’t captured in this graph is that load time no longer depends on application size. As long as users have loaded the app before, the browser should already have the translation from WebAssembly to native code cached from last time.
We were hoping that enabling WebAssembly would automatically improve download size too but it didn’t end up shrinking by much, especially after compression. It turns out that compressing asm.js code only ends up slightly bigger than compressing the equivalent WebAssembly code.
WebAssembly state of the world
At the time of writing, WebAssembly support is only enabled by default in Firefox and Chrome. Edge and Safari are still working on their implementations and haven’t released them yet. This will probably change soon so you should check the “Can I use” entry for the latest status.
Even though WebAssembly support is enabled in both Firefox and Chrome, Figma actually only uses WebAssembly in Firefox. We hit some showstopper bugs in Chrome’s WebAssembly implementation that are currently preventing us from enabling WebAssembly in Chrome:
- Bug 719172: Unlike Firefox, Chrome doesn’t cache its translated WebAssembly code. This means that the entire app must be re-translated every time the page loads, which actually makes our page load slower with WebAssembly than it does with asm.js.
- Bug 729768: Chrome’s WebAssembly implementation crashes sometimes when running Figma’s code. We’re assuming that this is a bug in V8 because the same code runs fine in Firefox.
Another thing to keep in mind is that browser debugger support is still emerging. It wasn’t prioritized for the WebAssembly MVP and isn’t really implemented yet. We’re still compiling to asm.js instead of WebAssembly for debugging in the meantime.
The future of WebAssembly
WebAssembly is brand new and so is understandably still rough around the edges. However, it’s a principled and practical approach to achieving native performance on the web that is well-poised to become core to how the web works.
One exciting aspect of WebAssembly is that it has much bigger ambitions than just being a target for C++ code. The design is appropriately general-purpose and it should be easy to add WebAssembly as an alternative output format for any compiler that targets native code. An official LLVM backend is in development that, when finished, will make it easy for any language using the LLVM toolchain to emit WebAssembly code directly.
This could potentially improve iteration time of the web platform. Browsers can focus on exposing low-level hardware primitives (WebGL, Bluetooth, USB, etc.) and leave the development of higher-level libraries to the community, which can evolve at a faster pace.
Even though WebAssembly isn’t quite ready yet, Figma is still investing in it because we believe that it’s an important part of the future of the web.
Like working on state-of-the-art web apps? Come work at Figma!