diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 22:58:53 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:17 -0300 |
| commit | b1485c97b493f7eaf65c6afdfb82e3065306b8fe (patch) | |
| tree | 890d411820859ef33f1adf3164176fe29e007961 /test/bench_util.zig | |
| parent | f0e162d287f44a562ff79e7c1d2cf81ace00c836 (diff) | |
| download | pardes-b1485c97b493f7eaf65c6afdfb82e3065306b8fe.tar.gz pardes-b1485c97b493f7eaf65c6afdfb82e3065306b8fe.zip | |
The PDF benches share their clock, fatal exit, hash, count parser and effect drain, and lspprobe is lspbench's probe subcommand
B4: test/bench_util.zig holds what pdf_bench, pdf_pointer_bench, pdf_scroll_bench and pdf_sections_bench each copied (nowNs x4, fatal x3 named per bench, mix x3, parsePositive/parseCount x3, drainEffects x2). They stay four entry points: pdf_bench links its own mupdf module (with its C source and c_heap) where the others link the core's, which one executable cannot import under one name, and their reports and identities are each bench's own. pdf_sections_bench had rotted since the pane's cursor and selections moved to its body and the render revision became next_raster_revision; it builds and runs again. C6: tools/lspprobe.zig is lspbench's `probe` subcommand (zig build lspbench -- probe <kind> <file> <line>:<col>), and the lspprobe build step goes; docs/lsp.md names the new command.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'test/bench_util.zig')
| -rw-r--r-- | test/bench_util.zig | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/test/bench_util.zig b/test/bench_util.zig new file mode 100644 index 00000000..9b91e621 --- /dev/null +++ b/test/bench_util.zig @@ -0,0 +1,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()) |_| {} +} |
