Hooks

This guide explains what lifecycle hooks are and how to use them.

Concepts

Lifecycle hooks provide control over a benchmark environment. A hook is a function with the signature fn () void. Its execution is not included in the benchmark reports.

There are 4 kinds of hooks:

HookWhen is it called?GoalExample
before_allAt the start of the benchmarkGlobal setupAllocate memory, initialize variables
before_eachBefore each iterationIteration setupSetup/allocate benchmark data
after_eachAfter each iterationIteration teardownReset/free benchmark data
after_allAt the end of the benchmarkGlobal teardownFree memory, deinit variables

Usage

zBench provides two ways to register hooks: globally or for a given benchmark.

Global registration

Hooks attached at runner-init level apply to every added benchmark.

pub fn main(init: std.process.Init) !void {
    const io = init.io;
    const stdout: std.Io.File = .stdout();

    var bench = zbench.Benchmark.init(init.gpa, .{ .hooks = .{
        .before_all = beforeAllHook,
        .after_all = afterAllHook,
    } });
    defer bench.deinit();

    try bench.add("Benchmark 1", myBenchmark, .{});
    try bench.add("Benchmark 2", myBenchmark, .{});

    try bench.run(io, stdout);
}

Both Benchmark 1 and Benchmark 2 will execute beforeAllHook and afterAllHook. Hooks are optional — before_each / after_each may be omitted.

Per-benchmark registration

Hooks can also be passed to add and addParam:

try bench.add("Benchmark 1", myBenchmark, .{
    .hooks = .{
        .before_all = beforeAllHook,
        .after_all = afterAllHook,
    },
});

try bench.add("Benchmark 2", myBenchmark, .{});

Here only Benchmark 1 will execute the hooks.