Skip to content

Commit 63e30e5

Browse files
committed
add zig bench
1 parent 576926b commit 63e30e5

File tree

5 files changed

+106
-0
lines changed

5 files changed

+106
-0
lines changed

samples/bench/bench.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { init as initDotNet } from "./dotnet/init.mjs";
33
import { init as initDotNetLLVM } from "./dotnet-llvm/init.mjs";
44
import { init as initGo } from "./go/init.mjs";
55
import { init as initRust } from "./rust/init.mjs";
6+
import { init as initZig } from "./zig/init.mjs";
67
import * as fixtures from "./fixtures.mjs";
78

89
/**
@@ -15,6 +16,8 @@ import * as fixtures from "./fixtures.mjs";
1516
const lang = process.argv[2];
1617
const baseline = new Map;
1718

19+
if (!lang || lang.toLowerCase() === "zig")
20+
await run("Zig", await initZig());
1821
if (!lang || lang.toLowerCase() === "rust")
1922
await run("Rust", await initRust());
2023
if (!lang || lang.toLowerCase() === "llvm")

samples/bench/zig/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.zig-cache
2+
zit-out

samples/bench/zig/build.zig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const std = @import("std");
2+
3+
pub fn build(b: *std.Build) void {
4+
const lib = b.addExecutable(.{
5+
.name = "zig",
6+
.root_source_file = b.path("main.zig"),
7+
.target = b.resolveTargetQuery(.{
8+
.cpu_arch = .wasm32,
9+
.os_tag = .freestanding,
10+
.cpu_features_add = std.Target.wasm.featureSet(&.{
11+
.simd128,
12+
.relaxed_simd,
13+
.tail_call,
14+
}),
15+
}),
16+
.use_llvm = true,
17+
.use_lld = true,
18+
.optimize = b.standardOptimizeOption(.{}),
19+
});
20+
lib.entry = .disabled;
21+
lib.rdynamic = true;
22+
lib.want_lto = true;
23+
b.installArtifact(lib);
24+
}

samples/bench/zig/init.mjs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { getNumber, getStruct } from "../fixtures.mjs";
2+
import fs from "fs/promises";
3+
4+
/** @returns {Promise<import("../bench.mjs").Exports>} */
5+
export async function init() {
6+
const source = await fs.readFile("./zig/zig-out/bin/zig.wasm");
7+
const { instance: { exports } } = await WebAssembly.instantiate(source, {
8+
x: {
9+
getNumber,
10+
getStruct: () => toCString(JSON.stringify(getStruct())),
11+
}
12+
});
13+
memory = exports.memory, cached = new Uint8Array(memory.buffer);
14+
15+
return {
16+
echoNumber: exports.echoNumber,
17+
echoStruct: () => JSON.parse(fromCString(exports.echoStruct())),
18+
fi: exports.fi
19+
};
20+
}
21+
22+
let memory, cached;
23+
const encoder = new TextEncoder("utf-8");
24+
const decoder = new TextDecoder("utf-8");
25+
26+
function toCString(str) {
27+
const memory = getMemoryCached();
28+
const { written } = encoder.encodeInto(str, memory);
29+
memory[written] = 0; // appending null terminator
30+
return 0; // naive: always writing to the start of the wasm memory
31+
}
32+
33+
function fromCString(ptr) {
34+
const memory = getMemoryCached();
35+
let len = 0;
36+
while (memory[ptr + len] !== 0) len++;
37+
const bytes = memory.subarray(ptr, ptr + len);
38+
return decoder.decode(bytes);
39+
}
40+
41+
function getMemoryCached() {
42+
if (cached.buffer.byteLength === memory.buffer.byteLength) return cached;
43+
return cached = new Uint8Array(memory.buffer);
44+
}

samples/bench/zig/main.zig

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const std = @import("std");
2+
3+
var arena = std.heap.ArenaAllocator.init(std.heap.wasm_allocator);
4+
const ally = arena.allocator();
5+
6+
pub const Data = struct {
7+
info: []const u8,
8+
ok: bool,
9+
revision: i32,
10+
messages: []const []const u8,
11+
};
12+
13+
extern "x" fn getNumber() i32;
14+
extern "x" fn getStruct() [*:0]const u8;
15+
16+
export fn echoNumber() i32 {
17+
return getNumber();
18+
}
19+
20+
export fn echoStruct() [*:0]const u8 {
21+
_ = arena.reset(.retain_capacity);
22+
const input = std.mem.span(getStruct());
23+
const parsed = std.json.parseFromSlice(Data, ally, input, .{}) catch unreachable;
24+
var output = std.ArrayList(u8).init(ally);
25+
std.json.stringify(parsed.value, .{}, output.writer()) catch unreachable;
26+
output.append(0) catch unreachable; // append null terminator
27+
return @ptrCast(output.items);
28+
}
29+
30+
export fn fi(n: i32) i32 {
31+
if (n <= 1) return n;
32+
return fi(n - 1) + fi(n - 2);
33+
}

0 commit comments

Comments
 (0)