feat: public API and build helper for consumers
- root.zig: re-exports Benchmark, Suite, Options, Format, Result, BenchFn, parse_duration_ns; also pulls every submodule into the test block so `zig build test` covers them. - build_helper.zig: add_bench_step(b, opts) factory that creates the benchmark executable (ReleaseFast by default), wires zbench and any extra modules, attaches an addRunArtifact forwarding `--` args, and registers a `zig build <step_name>` step.
This commit is contained in:
60
src/build_helper.zig
Normal file
60
src/build_helper.zig
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//! Build-system helper. Importable from a user's `build.zig` as
|
||||||
|
//! `@import("zbench_build")` (alongside `b.dependency("zbench", ...)`).
|
||||||
|
//!
|
||||||
|
//! Provides `add_bench_step`, a small factory that wires up a `zig build
|
||||||
|
//! bench` step around a user-written benchmark executable.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const BenchStepOptions = struct {
|
||||||
|
/// Build step name (e.g. "bench"). The `zig build <name>` invocation
|
||||||
|
/// triggers the run.
|
||||||
|
step_name: []const u8 = "bench",
|
||||||
|
/// Executable name. Defaults to `step_name`.
|
||||||
|
exe_name: ?[]const u8 = null,
|
||||||
|
/// Source file containing the user's `pub fn main(init)`.
|
||||||
|
root: std.Build.LazyPath,
|
||||||
|
target: std.Build.ResolvedTarget,
|
||||||
|
/// Optimize mode for the benchmark exe. ReleaseFast by default — there is
|
||||||
|
/// rarely a reason to benchmark debug builds.
|
||||||
|
optimize: std.builtin.OptimizeMode = .ReleaseFast,
|
||||||
|
/// The `zbench` module from `b.dependency("zbench", ...).module("zbench")`.
|
||||||
|
zbench: *std.Build.Module,
|
||||||
|
/// Extra modules to import into the benchmark exe (e.g. the code under
|
||||||
|
/// test).
|
||||||
|
extra_imports: []const ExtraImport = &.{},
|
||||||
|
/// Step description shown by `zig build --help`.
|
||||||
|
description: []const u8 = "Run benchmarks",
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ExtraImport = struct {
|
||||||
|
name: []const u8,
|
||||||
|
module: *std.Build.Module,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Wire up a `zig build <step_name>` step that compiles the benchmark exe and
|
||||||
|
/// runs it, forwarding any CLI args after `--` to the benchmark.
|
||||||
|
///
|
||||||
|
/// Returns the created `*Step.Compile` so the caller can attach further
|
||||||
|
/// configuration (link options, install rules, etc.) if needed.
|
||||||
|
pub fn add_bench_step(b: *std.Build, opts: BenchStepOptions) *std.Build.Step.Compile {
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = opts.exe_name orelse opts.step_name,
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = opts.root,
|
||||||
|
.target = opts.target,
|
||||||
|
.optimize = opts.optimize,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
exe.root_module.addImport("zbench", opts.zbench);
|
||||||
|
for (opts.extra_imports) |imp| {
|
||||||
|
exe.root_module.addImport(imp.name, imp.module);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run = b.addRunArtifact(exe);
|
||||||
|
if (b.args) |args| run.addArgs(args);
|
||||||
|
|
||||||
|
const step = b.step(opts.step_name, opts.description);
|
||||||
|
step.dependOn(&run.step);
|
||||||
|
return exe;
|
||||||
|
}
|
||||||
44
src/root.zig
Normal file
44
src/root.zig
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//! zbench — Go-style benchmarking for Zig 0.16+.
|
||||||
|
//!
|
||||||
|
//! ```zig
|
||||||
|
//! const std = @import("std");
|
||||||
|
//! const zbench = @import("zbench");
|
||||||
|
//!
|
||||||
|
//! pub fn main(init: std.process.Init) !void {
|
||||||
|
//! var suite = zbench.Suite.init(init.gpa, init.io);
|
||||||
|
//! defer suite.deinit();
|
||||||
|
//!
|
||||||
|
//! try suite.add("append", bench_append);
|
||||||
|
//! try suite.run_cli(init);
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn bench_append(b: *zbench.Benchmark) !void {
|
||||||
|
//! var list: std.ArrayListUnmanaged(u8) = .empty;
|
||||||
|
//! defer list.deinit(b.allocator);
|
||||||
|
//! b.reset_timer();
|
||||||
|
//! var i: u64 = 0;
|
||||||
|
//! while (i < b.n) : (i += 1) {
|
||||||
|
//! try list.append(b.allocator, @intCast(i & 0xff));
|
||||||
|
//! }
|
||||||
|
//! b.keep(list.items);
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
const bench = @import("benchmark.zig");
|
||||||
|
const suite_mod = @import("suite.zig");
|
||||||
|
const runner = @import("runner.zig");
|
||||||
|
|
||||||
|
pub const Benchmark = bench.Benchmark;
|
||||||
|
pub const BenchFn = bench.BenchFn;
|
||||||
|
pub const Suite = suite_mod.Suite;
|
||||||
|
pub const Options = suite_mod.Options;
|
||||||
|
pub const Format = suite_mod.Format;
|
||||||
|
pub const Result = runner.Result;
|
||||||
|
pub const parse_duration_ns = suite_mod.parse_duration_ns;
|
||||||
|
|
||||||
|
test {
|
||||||
|
_ = @import("alloc.zig");
|
||||||
|
_ = @import("stats.zig");
|
||||||
|
_ = @import("runner.zig");
|
||||||
|
_ = @import("suite.zig");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user