Fast WebAssembly interpreter
See the codeA WebAssembly runtime written in Zig, designed to be fast, compact, and easy to embed.
In my benchmarks, wasmz is currently the fastest WebAssembly interpreter I have tested.
The benchmark chapter also includes notes on the parser and interpreter optimizations used in wasmz.
If you find workloads where wasmz has a clear disadvantage, please let me know. I will do my best to optimize them :)
Validated with production WASM workloads:
Full implementation including:
# Install from the latest release
curl -fsSL https://raw.githubusercontent.com/Ray-D-Song/wasmz/main/scripts/install.sh | bash
# Run a WASM file
wasmz module.wasm
# Call a function with arguments
wasmz module.wasm add 3 4
# Output: 7
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/Ray-D-Song/wasmz/main/scripts/install.sh | bash
Windows:
powershell -ExecutionPolicy Bypass -c "iwr https://raw.githubusercontent.com/Ray-D-Song/wasmz/main/scripts/install.ps1 -UseBasicParsing | iex"
By default, these install to:
~/.local/bin/wasmz on Linux / macOS%LOCALAPPDATA%\wasmz\bin\wasmz.exe on Windows# List exported functions
wasmz module.wasm
# Call a function
wasmz module.wasm add 3 4
# Run _start with WASI arguments
wasmz program.wasm --args "--verbose --output=result.txt"
# Reactor mode (call _initialize first)
wasmz library.wasm --reactor --func process
# Memory statistics
wasmz program.wasm --mem-stats
git clone https://github.com/Ray-D-Song/wasmz.git
cd wasmz
make build
| Command | Description |
|---|---|
make build | ReleaseSafe build (recommended) |
make build-debug | Debug build (unoptimized) |
make release | ReleaseFast build (maximum performance) |
make test | Run all unit tests |
make install | Install to ~/.local/bin |
make uninstall | Remove ~/.local/bin/wasmz |
const std = @import("std");
const wasmz = @import("wasmz");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var engine = try wasmz.Engine.init(allocator, .{});
defer engine.deinit();
const bytes = try std.fs.cwd().readFileAlloc(allocator, "module.wasm", 1024 * 1024);
defer allocator.free(bytes);
var module = try wasmz.Module.compile(engine, bytes);
defer module.deinit();
var store = try wasmz.Store.init(allocator, engine);
defer store.deinit();
var instance = try wasmz.Instance.init(&store, module, .empty);
defer instance.deinit();
const result = try instance.call("add", &.{ .{ .i32 = 1 }, .{ .i32 = 2 } });
std.debug.print("Result: {d}\n", .{result.ok.?.readAs(i32)});
}
Build the shared library:
make clib
Output:
zig-out/lib/libwasmz.{so,dylib,dll}zig-out/include/wasmz.hFull documentation is available online at https://ray-d-song.github.io/wasmz/.
Source files live under docs/src, including:
MIT License - see LICENSE file for details.
271 commits
1 commits
Zig
95.2%
Shell
1.5%
C
1.5%
Fast WebAssembly interpreter
See the codeA WebAssembly runtime written in Zig, designed to be fast, compact, and easy to embed.
In my benchmarks, wasmz is currently the fastest WebAssembly interpreter I have tested.
The benchmark chapter also includes notes on the parser and interpreter optimizations used in wasmz.
If you find workloads where wasmz has a clear disadvantage, please let me know. I will do my best to optimize them :)
Validated with production WASM workloads:
Full implementation including:
# Install from the latest release
curl -fsSL https://raw.githubusercontent.com/Ray-D-Song/wasmz/main/scripts/install.sh | bash
# Run a WASM file
wasmz module.wasm
# Call a function with arguments
wasmz module.wasm add 3 4
# Output: 7
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/Ray-D-Song/wasmz/main/scripts/install.sh | bash
Windows:
powershell -ExecutionPolicy Bypass -c "iwr https://raw.githubusercontent.com/Ray-D-Song/wasmz/main/scripts/install.ps1 -UseBasicParsing | iex"
By default, these install to:
~/.local/bin/wasmz on Linux / macOS%LOCALAPPDATA%\wasmz\bin\wasmz.exe on Windows# List exported functions
wasmz module.wasm
# Call a function
wasmz module.wasm add 3 4
# Run _start with WASI arguments
wasmz program.wasm --args "--verbose --output=result.txt"
# Reactor mode (call _initialize first)
wasmz library.wasm --reactor --func process
# Memory statistics
wasmz program.wasm --mem-stats
git clone https://github.com/Ray-D-Song/wasmz.git
cd wasmz
make build
| Command | Description |
|---|---|
make build | ReleaseSafe build (recommended) |
make build-debug | Debug build (unoptimized) |
make release | ReleaseFast build (maximum performance) |
make test | Run all unit tests |
make install | Install to ~/.local/bin |
make uninstall | Remove ~/.local/bin/wasmz |
const std = @import("std");
const wasmz = @import("wasmz");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var engine = try wasmz.Engine.init(allocator, .{});
defer engine.deinit();
const bytes = try std.fs.cwd().readFileAlloc(allocator, "module.wasm", 1024 * 1024);
defer allocator.free(bytes);
var module = try wasmz.Module.compile(engine, bytes);
defer module.deinit();
var store = try wasmz.Store.init(allocator, engine);
defer store.deinit();
var instance = try wasmz.Instance.init(&store, module, .empty);
defer instance.deinit();
const result = try instance.call("add", &.{ .{ .i32 = 1 }, .{ .i32 = 2 } });
std.debug.print("Result: {d}\n", .{result.ok.?.readAs(i32)});
}
Build the shared library:
make clib
Output:
zig-out/lib/libwasmz.{so,dylib,dll}zig-out/include/wasmz.hFull documentation is available online at https://ray-d-song.github.io/wasmz/.
Source files live under docs/src, including:
MIT License - see LICENSE file for details.
271 commits
1 commits
Zig
95.2%
Shell
1.5%
C
1.5%