diff --git a/packages/core/bench_runner.zig b/packages/core/bench_runner.zig new file mode 100644 index 0000000..1f3c1ca --- /dev/null +++ b/packages/core/bench_runner.zig @@ -0,0 +1,51 @@ +const std = @import("std"); +const builtin = @import("builtin"); + +pub const Options = struct { + iterations: usize = 100, +}; + +fn percentile(samples: []u64, perc: f64) u64 { + const idx = @as(usize, @intFromFloat(perc * @as(f64, @floatFromInt(samples.len - 1)))); + return samples[idx]; +} + +fn runBench(name: []const u8, func: *const fn() anyerror!void, opts: Options) !void { + const samples = try std.heap.page_allocator.alloc(u64, opts.iterations); + defer std.heap.page_allocator.free(samples); + + var timer = try std.time.Timer.start(); + for (samples, 0..) |*s, i| { + _ = i; + const start = timer.read(); + try func(); + const end = timer.read(); + s.* = end - start; + } + + std.sort.heap(u64, samples, {}, std.sort.asc(u64)); + + var total: u128 = 0; + for (samples) |s| total += s; + + const avg = total / samples.len; + const min = samples[0]; + const max = samples[samples.len - 1]; + const p75 = percentile(samples, 0.75); + const p99 = percentile(samples, 0.99); + + std.debug.print("{s}: avg {d} ns (min {d}, p75 {d}, p99 {d}, max {d})\n", .{ name, avg, min, p75, p99, max }); +} + + +pub fn main() !void { + // Print discovered test names + for (builtin.test_functions) |t| { + std.debug.print("found test: {s}\n", .{t.name}); + } + + for (builtin.test_functions) |t| { + if (std.mem.indexOf(u8, t.name, "bench") == null) continue; + try runBench(t.name, t.func, .{}); + } +} diff --git a/packages/core/build.zig b/packages/core/build.zig index 12a1952..2e4bba0 100644 --- a/packages/core/build.zig +++ b/packages/core/build.zig @@ -99,4 +99,27 @@ pub fn build(b: *std.Build) !void { &install_step.step, test_debugger, }); + + // ---------------- Benchmarks ---------------- + const bench_tests = b.addTest(.{ + .root_source_file = b.path("src/wasm.zig"), + .name = "bench", + .target = target, + .optimize = optimize, + .test_runner = .{ + .path = b.path("bench_runner.zig"), + .mode = .simple, + }, + }); + + const run_bench = b.addRunArtifact(bench_tests); + if (b.args) |args| { + run_bench.addArgs(args); + } + + const bench_step = b.step("bench", "Run benchmarks"); + pipe(.{ + &run_bench.step, + bench_step, + }); } diff --git a/packages/core/src/main.zig b/packages/core/src/main.zig index f6d0cce..8f07745 100644 --- a/packages/core/src/main.zig +++ b/packages/core/src/main.zig @@ -29,4 +29,5 @@ test { _ = @import("./renderer/Renderer.zig"); _ = @import("./renderer/gradient.zig"); _ = @import("./layout/Selection.zig"); + _ = @import("./sample_bench.zig"); } diff --git a/packages/core/src/sample_bench.zig b/packages/core/src/sample_bench.zig new file mode 100644 index 0000000..c7988c9 --- /dev/null +++ b/packages/core/src/sample_bench.zig @@ -0,0 +1,9 @@ +const std = @import("std"); + +pub const options = .{ .iterations = 10 }; + +test "simple bench" { + var sum: usize = 0; + for (0..1000) |i| sum += i; + std.mem.doNotOptimizeAway(sum); +} diff --git a/packages/core/src/wasm.zig b/packages/core/src/wasm.zig index 74ed841..c2c3475 100644 --- a/packages/core/src/wasm.zig +++ b/packages/core/src/wasm.zig @@ -586,4 +586,5 @@ test { _ = @import("./uni/LineBreakStream.zig"); _ = @import("./layout/v2/text/white-space-processor.zig"); _ = @import("./layout/v2/text/LinesBuilder.zig"); + _ = @import("./sample_bench.zig"); }