summaryrefslogtreecommitdiff
path: root/test/bench_util.zig
blob: 9b91e621f943828b78b42d1208e42453abeac0e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//! What the PDF benches share: a clock, a fatal exit named for the bench, a
//! seeded hash, a count parser and the core's effect drain.
const std = @import("std");

pub fn nowNs() u64 {
    var ts: std.c.timespec = undefined;
    _ = std.c.clock_gettime(.MONOTONIC, &ts);
    return @as(u64, @intCast(ts.sec)) *| 1_000_000_000 +| @as(u64, @intCast(ts.nsec));
}

/// `fatal` for the bench called `who`: says so, prefixed, and exits 1.
pub fn Fatal(comptime who: []const u8) type {
    return struct {
        pub fn f(comptime format: []const u8, args: anytype) noreturn {
            std.debug.print(who ++ ": " ++ format ++ "\n", args);
            std.process.exit(1);
        }
    };
}

/// A seeded hash of `value`'s bytes; a comptime integer hashes as a u64.
pub fn mix(seed: u64, value: anytype) u64 {
    const Value = @TypeOf(value);
    const Stable = switch (@typeInfo(Value)) {
        .comptime_int => u64,
        else => Value,
    };
    var stable: Stable = value;
    return std.hash.Wyhash.hash(seed, std.mem.asBytes(&stable));
}

/// A flag's value as a count in 1..`maximum`, or `fatal` saying why not.
pub fn parsePositive(comptime fatal: anytype, name: []const u8, text: []const u8, maximum: usize) usize {
    const value = std.fmt.parseUnsigned(usize, text, 10) catch
        fatal("{s} expects a positive integer", .{name});
    if (value == 0 or value > maximum)
        fatal("{s} must be in 1..{d}", .{ name, maximum });
    return value;
}

pub fn drainEffects(core: anytype) void {
    while (core.nextEffect()) |_| {}
}