Alex Williams Alex Williams is a seasoned full-stack developer and the owner of Hosting Data UK. After graduating from the University of London with a major in IT, Alex worked as a developer leading various projects for clients from all over the world for almost 10 years. Recently, Alex switched to being an independent IT consultant and started his own blog. There, he explores web development, data management, digital marketing, and solutions for online business owners just starting out.

WebAssembly runtimes compared

6 min read 1725

Webassembly Runtimes Compared

Introduction and background

With the recent release of Wasmer 1.0, let’s take a broad-spectacled look at WebAssembly and its popular runtimes, including the exciting WASI interface.

To jump the comparison section, click here.

ISAs and WebAssembly

Implementable inside server/client web apps, WebAssembly emphasizes portability and predictability. Alongside RISC-V, it’s a relatively new instruction set architecture (ISA) developed over the last decade able to run alongside host languages.

ISAs themselves are abstract computer science models representing computers. Real-world enactments of ISAs are called implementations — e.g., a central processing unit (CPU). ISAs also determine how machine code behaves on implementations containing that ISA.

While RISC-V will pave the way for process innovations in hardware/extensible software architectures (e.g., open source processors), WebAssembly, often shortened to Wasm, stands out for offering compilations, especially for browsers.

In short, WebAssembly can run alongside the JavaScript engine that powers the web’s browsers. You can compile other advanced languages to it — Rust, C/C++, etc. — for better performance using its low-level binary format that combines small file sizes with superior speed. You’re not writing WebAssembly; you’re simply using it to compile.

Wasm runtime libraries overview: A brief history

It begins with Java

Let’s start with Java. The quintessential dream of computing was compatibility: the ’90s dreamt up a Java world where you could “write once, run anywhere” (WORA) — although this wasn’t its originally intended use. This worked with simple apps but became a problem with different operating systems, versions, and devices attempting to run that code.

WORA transformed into WODE (“write once, debug everywhere”), with other issues like needing the target to use JVM and then having to do extra programming in just Java or another JVM language. JavaScript took a step closer to the dream, becoming the universal language of the web.

WebAssembly enters the stage

That’s the basic context for WebAssembly. This compact form is designed for rapid executions and bite-sized binaries. It operates sandboxed, as does JavaScript, offering protection when running code online without extra risks to your system, and is compatible with advanced programming languages.

In a later section, we will talk about the WASI interface, which is striving to standardize essential operations to get WebAssembly closer to the dream of running once-made code anywhere. WASI/Wasm is a better solution than JavaScript for running the following outside of the browser:

For now, the issue of where you run is still an important factor developers need to deal with, not to mention managing unstructured hybrid data streams via the cloud and on-premises using NoSQL databases.

Technical overview: Runtime libraries

When running native code in the browser, each time source code gets transcribed to the relevant target language by a compiler, this can lead to massive program code enlargement. The workaround is to use a compiler with compiler-specific auxiliary functions.

WebAssembly Wasm Compiler Auxillary Function

WebAssembly also massively reduces processing times in browsers. As this post covers runtimes broadly, we won’t go into the specific details of runtime structure and representations such as store and stack, nor other structure elements encompassing the conceptual machinery of WebAssembly, such as values and module instances and their auxiliary syntax.

Comparison: 4 interesting standalone Wasm runtimes

Wasmer

Version 1.0 of Wasmer was just released in January 2021 with a stabilized API and easier usage. It offers exceedingly lightweight containers executable from anywhere, whether the cloud, desktop, or IOT device. Wasmer is embeddable inside any programming language, acting as a library you embed in whatever language; truly use WebAssembly wherever.

Key Wasmer features:

  • Pluggability: Compatible with the various compilation frameworks, whatever you need (e.g., Cranelift)
  • Speed/safety: Able to run Wasm at nearly native speed in a completely sandboxed setting.
  • Universality: Works on any platform (Windows, Linux, and so on) and chipset
  • Support: Compliant with WebAssembly test suite standards with a large base of developer and contributor community support

Install Wasmer with a single command.

Wasmtime

Wasmtime is an efficient, compact solution for working with the latest WASI/WebAssembly innovations. If you’re using the following languages, embed Wastime (can also be hosted by the Bytecode Alliance): Rust, Python, C, .NET, and Go. Outside of the alliance, you can find embedding APIs for Java, Perl, Targeting, Zig, and Ruby.

Key Wasmtime features:

  • Compact: Non-demanding standalone runtime that you can scale up as your needs grow. Can work with small chips or be utilized with massive servers. Embeddable on almost any app
  • Easily modified: Tweak Wasmtime in advance for pre-compilations, generate light-speed code using Lightbeam, or use for runtime interpretations. Configure for whatever you need Wasm to accomplish
  • Speedy: Compatible with Cranelift; perform high-resolution runtime machine coding
  • WASI-compatible: Supports a flush of APIs, allowing you to implement alongside the host via the WASI interface
  • Support: Compliant with WebAssembly test suite standards with a large base of developer and contributor community support

Wasmtime installation/embedding guide.

Lucet

Lucet was announced on 28 March 2019. It’s a lesser-known compiler/runtime native to WebAssembly and an option for developers who want to execute potentially hazardous Wasm programs contained in their application.

A Bytecode Alliance open source community project, you can use it for running untrusted code, whether the infrastructure, device, or OS — a capability drawn from established examples used in web browsers.

Key Lucet features:

  • Fast specialization: An open source project, run untrusted programs at near-native speed
  • WASI-friendly: Use WebAssembly outside of your browser. Lucet supports the WebAssembly System Interface on the Fastly edge cloud
  • Supports many languages: This includes Typescript, Rust, C/C++, and many more are in development
  • Massively lowered runtime footprint: Any request Fastly mediates can be executed by a WebAssembly instance representing all of the many thousands of requests per second per process, without extra web app security risks
  • Ahead-of-time (AOT) compilation support: Configure AOT compilations to streamline runtime overhead and design

Their compilation guide needs to be updated.

WebAssembly Micro Runtime (WAMR)

The final standalone runtime we’ll cover is WebAssembly Micro Runtime (WAMR). It has a tiny footprint and is made up of three components:

  1. A so-called iwasm VM core, which offers just-in-time (JIT) and AOT compilation, and WebAssembly interpretation
  2. An application framework that allows for building out multiple Wasm apps that can run on devices and for IoT purposes
  3. Dynamic/remote application management from the cloud or host environment

Key WAMR (iwasm) features:

  • Fast: Runs at near-native speed (AOT)
  • Compliance: Compliance standards for the W3C WASM MVP
  • Small footprint: Binary size of only 85K (interpreter) and 50K (AOT) and requires few memory resources

There isn’t a great deal happening with community support/news here outside of resolving bug issues.



WASI: An eagle-eyed runtimes vantage

To browser, or not to browser

As the name suggests, WebAssembly is designed to run via the web on browsers. But it has the potential for a massive non-web future thanks to WASI. This system interface allows for running WebAssembly outside the web as well as inside it.

When using the web ecosystem, WebAssembly is able to work with modern browser APIs, remain compatible with its standard security model, and retain the portability of the web, all while maintaining adaptable development and design for future evolution. This is a high-level system without trade-offs in security, especially as compared to JavaScript.

For running Wasm outside the web using WASI, standalone Wasm runtimes can work as interpreters / “hosts.” The promise of using it in non-web environments (with or without a JavaScript VM like Node.js) stretches from testing purposes using basic shells to commercial apps for IoT devices, mobile/desktop apps, data center servers, or as an executable inside bigger programs.

What is WASI, and why is it so exciting?

WASI stands for WebAssembly System Interface, i.e., it’s Wasm’s modular system interface. Let’s explore this from a high level so you can get an idea of just why WASI is so exciting. Here are a few of the possible ways WASI could manifest (assuming the high-level aims of WASI are realized):

1.) Cross-platform apps/games

The dream here is cross-platform games and applications from a single file, also harnessing the power of PlayOS. The mechanism behind this: one binary executable capable of being realized on any platform containing the WebAssembly runtime — communities building libraries that map these, with WebAssembly itself doing the foundational work.

2.) Reusing source code

The benefit here is obvious. You could reuse source code across various platforms for your application architecture — for instance, mobile/desktop, server and client, and even IoT.

3.) Single runtime able to execute WASI-friendly (Wasm) applications

This reduces compiling demands enormously. No need to stitch together different languages and their separate runtimes — one runtime capable of realizing every one!

4.) Grouping many targets as one target

This is really about containerization — a compilation of many applications and their dependencies into one or few Wasm files. Everything is Wasm-led, boosting usability and reducing the need for finicky containers.

With all that said, WASI is still in development, and all these examples are high-level conceptualizations.

Wrapping up

To summarize the runtime options:

  • Wasmer has the best overall support compatibility with every programming language at super-speed
  • Wasmtime is lightning-fast and compact, with good configurability but fewer languages supported
  • Lucet is a specialized solution for running untrusted WebAssembly programs inside a larger application
  • WAMR runs with a small footprint

N.B., this list isn’t exhaustive; there are many awesome WebAssembly runtimes.

That’s it — we’ve covered a decade span in this guide. I’ve fleshed out some of the key features of WebAssembly’s most popular (and up-and-coming) runtimes: similarities and differences, from improving browser rendering to non-web possibilities. I’ve placed this under the umbrella perspective of WASI, as WASI is based on maximum portability.

Programs that contain WebAssembly will have this additional system interface acting as a foundation that other programs can be built atop. This takes on the challenge of a truly universal interface, which Java first set about accomplishing, and goes hand-in-hand with the shift towards data science to optimize businesses.

Security will be a major problem as extreme universality becomes more possible — a world where a WASI program can be executed from any source. New security systems developed by united cross-industry efforts will need to be developed to meet this demand, one such example being the Lucet runtime.

Get setup with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    LogRocket.init('app/id');
    Add to your HTML:

    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • ngrx middleware
    • Vuex plugin
Get started now
Alex Williams Alex Williams is a seasoned full-stack developer and the owner of Hosting Data UK. After graduating from the University of London with a major in IT, Alex worked as a developer leading various projects for clients from all over the world for almost 10 years. Recently, Alex switched to being an independent IT consultant and started his own blog. There, he explores web development, data management, digital marketing, and solutions for online business owners just starting out.

One Reply to “WebAssembly runtimes compared”

  1. Does any of the listed runtimes support step-by-step (from source language like C++ or rust) debugging yet?

Leave a Reply