WASM & WASI: Turbocharging Your Web Development

Published on
Gyanaranjan Sahoo-
5 min read

Overview

Wasm-wasi

Introduction

WebAssembly (Wasm) is a binary instruction format for a stack-based virtual machine. It's designed as a portable target for the compilation of high-level languages like C, C++, and Rust, enabling deployment on the web for client and server applications. In this blog post, we will explore WebAssembly, the WebAssembly System Interface (WASI), and various WebAssembly runtimes.

WebAssembly, WASI, and Runtimes: The Need for Speed in Web Development

Alright folks, gather around. Today, we're going to talk about something that's going to make your web development faster than a cheetah on a sugar rush. We're talking about WebAssembly, WASI, and various WebAssembly runtimes. WebAssembly is a low-level, binary format that is fast, efficient, and secure. It serves as a compilation target for various languages, allowing them to run in the browser (or on the server-side using Node.js).

WebAssembly: The Cheetah of Web Development

WebAssembly, or Wasm for short, is like the cheetah of web development. It's a low-level, binary format that's faster than a hiccup. It's designed to run at near-native speed, bringing the performance of languages like C and C++ to the web.

Imagine you're a JavaScript developer, and you've been running a marathon with a backpack full of rocks (don't ask why, it's just a metaphor). Suddenly, you're handed a pair of roller skates. That's what using WebAssembly feels like.

Here's a little taste of what WebAssembly code looks like(wat):

(module
  (func $add (param $a i32) (param $b i32) (result i32)
    get_local $a
    get_local $b
    i32.add)
  (export "add" (func $add))
)

This module exports a function called add that takes two 32-bit integers as input and returns their sum.

What is WASI?

The WebAssembly System Interface (WASI) is a system interface for WebAssembly. It provides a set of APIs for WebAssembly modules to interact with the system (like file system, network, etc.). WASI ensures the portability of WebAssembly, allowing it to run in various environments.

WebAssembly Runtimes: The Race Tracks

Finally, we have the WebAssembly runtimes. These are like the race tracks where our cheetah runs. There are several runtimes available, each with its own strength

1. Wasmtime

Wasmtime is a standalone runtime for WebAssembly & WASI, using the Cranelift JIT compiler. It aims to be efficient and secure. Here's how you would run a WebAssembly file with Wasmtime:

wasmtime app.wasm

2. Wasmer

Wasmer is a fast and secure standalone WebAssembly runtime that aims to be fully compatible with WASI, Emscripten, Rust and Go. Running a WebAssembly file with Wasmer is as simple as:

wasmer run app.wasm

3. Lucet

Lucet is a WebAssembly runtime developed by Fastly. It uses a custom compiler backend to optimize WebAssembly code for performance. Here's how you would run a WebAssembly file with Lucet:

lucetc-wasi app.wasm -o app.so
lucet-wasi app.so

4. Nodejs

While primarily a JavaScript runtime, also provides experimental support for WebAssembly. You can run WebAssembly code in Node.js like this:

const fs = require('fs');
const wasm = fs.readFileSync('app.wasm');
const { instance } = await WebAssembly.instantiate(wasm, {});

console.log(instance.exports.add(2, 3));

WASIX: The Supercharged WASI

Just when you thought things couldn't get any better, let me introduce you to WASIX, a superset of WASI. WASIX enhances WASI's capabilities, allowing WebAssembly modules to interact with the system in even more ways.

One of the key enhancements that WASIX brings to the table is asynchronous I/O support. In the world of web development, being able to perform I/O operations asynchronously is a big deal. It means your application can continue doing other things instead of waiting for a file to be read or a network request to complete. This can significantly improve the responsiveness and performance of your application.

Here's a simple example of what asynchronous file reading might look like in WASIX:

use wasix_async::fs::File;
use futures::prelude::*;

async fn read_file() -> wasix_async::Result<()> {
    let mut file = File::open("hello.txt").await?;
    let mut contents = String::new();
    file.read_to_string(&mut contents).await?;
    println!("{}", contents);
    Ok(())
}

In this example, the read_file function is asynchronous. It opens a file, reads its contents into a string, and then prints the string. All of this is done without blocking the rest of the application.

Another enhancement that WASIX provides is improved networking support. WASI has limited networking capabilities, but WASIX extends these to include things like DNS resolution, which is essential for making network requests.

With WASIX, your WebAssembly modules can do more than ever before. It's like giving them a set of superpowers. So, if you're looking to take your web development to the next level, WASIX might just be the tool you need.

Rust and WebAssembly

Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety. It's a perfect match for WebAssembly.

Here's a simple Rust function that adds two numbers:

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

To compile this to WebAssembly, we can use the wasm-pack tool:

wasm-pack build --target web

This will generate a .wasm file that can be run in any WebAssembly runtime.

Running Rust Code in a WebAssembly Runtime

Let's take our compiled Rust code for a spin in a WebAssembly runtime. We'll use Wasmtime for this example:

wasmtime add.wasm --invoke add 5 7

This will invoke the add function in the add.wasm module, passing 5 and 7 as arguments. The result, 12, will be printed to the console

Conclusion

So, there you have it. With WebAssembly, WASI, WASIX, and Rust, you can supercharge your web development and run your code at near-native speed. It's like strapping a rocket to your JavaScript and watching it blast off into the stratosphere. Enjoy the ride!