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.
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.
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.
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.
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 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.
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:
Install Wasmer with a single command.
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:
Wasmtime installation/embedding guide.
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:
Their compilation guide needs to be updated.
The final standalone runtime we’ll cover is WebAssembly Micro Runtime (WAMR). It has a tiny footprint and is made up of three components:
Key WAMR (iwasm) features:
There isn’t a great deal happening with community support/news here outside of resolving bug issues.
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.
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):
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.
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.
This reduces compiling demands enormously. No need to stitch together different languages and their separate runtimes — one runtime capable of realizing every one!
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.
To summarize the runtime options:
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.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ 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>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
One Reply to "WebAssembly runtimes compared"
Does any of the listed runtimes support step-by-step (from source language like C++ or rust) debugging yet?