• Home
  • blog
  • WebAssembly: Solving Performance Problems on the Web

WebAssembly: Solving Performance Problems on the Web

In modern JavaScript, the goal is often to find every way to optimize performance in the browser. There are times when web applications demand high performance and expect browsers to keep up.

Traditional JavaScript has performance limitations because of how the engine treats the language. An interpreted (or even JIT-compiled) language that’s rendered as part of a page can only get so much — even from the most powerful hardware.

WebAssembly is designed from the ground up to solve the performance problem. It can overcome bottleneck issues that traditional JavaScript wasn’t meant to solve. In WebAssembly, there’s no need to parse and interpret code. WebAssembly takes full advantage of its bytecode format to grant you runtime speeds that match native programs.

Think of it another way: imagine traditional JavaScript as a good, all-purpose tool that can get you anywhere. WebAssembly, in contrast, is the high-performance solution capable of achieving near-native speeds. These are two separate programming tools now at your disposal.

The questions for me are these: does WebAssembly replace good old traditional JavaScript? If not, is it worth the investment in learning WebAssembly?

What Is WebAssembly?

WebAssembly is a different type of code that can be sent to the browser. It’s in bytecode, format meaning that it’s shipped in low-level assembly language by the time it reaches the browser. The bytecode is not meant to be written by hand, but can be compiled from any programming language such as C++ or Rust. The browser can then take any WebAssembly code, load it as native code, and achieve high performance.

You can think of this WebAssembly bytecode as a module: the browser can fetch the module, load it, and execute it. Each WebAssembly module has import and export capabilities that behave a lot like a JavaScript object. A WebAssembly module acts a lot like any other JavaScript code, minus the fact that it runs at near-native speeds. From a programmer’s perspective, you can work with WebAssembly modules the same way you work with current JavaScript objects. This means that what you already know about JavaScript and the web transfers into WebAssembly programming as well.

The WebAssembly tooling often consists of a C++ compiler. There are many tools in current development, but one that has reached maturity is Emscripten. This tool compiles C++ code into a WebAssembly module and builds standards-compliant modules that can run anywhere. The compiled output will have a WASM file extension to indicate that it’s a WebAssembly module.

One advantage in WebAssembly is that you have all the same HTTP caching headers when you fetch modules. Plus, you can cache WASM modules using IndexedDB, or you can cache modules using session storage. The caching strategy revolves around caching fetch API requests and avoiding yet another request by keeping a local copy. Since WebAssembly modules are in bytecode format, you can treat the module as a byte array and store it locally.

Now that we know what WebAssembly is, what are some of its limitations?

Known Limitations

JavaScript runs in a different environment from any typical C++ program. Therefore, limitations include what native APIs can do in a browser environment.

Network functions must be asynchronous and non-blocking operations. All the underlying JavaScript networking functions are asynchronous in the browser’s Web API. WebAssembly, however, doesn’t benefit from asynchronous I/O-bound operations. An I/O operation must wait for the network to respond, which makes all near-native performance gains negligible.

Code that runs in a browser, runs in a sandboxed environment and doesn’t have access to the file system. You may create an in-memory virtual file system instead that comes preloaded with data.

The application’s main loop uses co-operative multitasking, and each event has a turn to execute. An event on the web often comes from a mouse click, finger tap, or a drag and drop operation. The event must return control to the browser so that other events can be processed. It’s wise to avoid hijacking the main event loop, as this can turn into a debugging nightmare. DOM events are often tied to UI updates, which are expensive. And this brings us to another limitation.

WebAssembly cannot access the DOM; it leans on JavaScript functions to make any changes. Currently, there’s a proposal to allow interoperability with DOM objects on the web. If you think about it, DOM repaints are slow and expensive. All the gains one gets from near-native performance get thwarted by the DOM. One solution is to abstract the DOM into an in-memory local copy that can be reconciled later by JavaScript.

In WebAssembly, some good advice is to stick to what can perform very fast. Use the tool for the job that yields the most performance gains while avoiding pitfalls. Think of WebAssembly as this super-high-speed system that runs well in isolation without any blockers.

Browser compatibility in WebAssembly is dismal, except in modern browsers. There’s no support in IE. Edge 16+, however, does support WebAssembly. All modern big players like Firefox 52+, Safari 11+, and Chrome 57+ support WebAssembly. One idea is to have feature detection and do feature parity between WebAssembly modules and a fallback to JavaScript. This way you don’t break the web and modern browsers get all the performance gains from WebAssembly.

Can I Use wasm? Data on support for the wasm feature across the major browsers from

The post WebAssembly: Solving Performance Problems on the Web appeared first on SitePoint.