From b1485c97b493f7eaf65c6afdfb82e3065306b8fe Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 22:58:53 -0300 Subject: 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 :), and the lspprobe build step goes; docs/lsp.md names the new command. Co-Authored-By: Claude Opus 5.5 --- test/pdf_scroll_bench.zig | 43 +++++++++---------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) (limited to 'test/pdf_scroll_bench.zig') diff --git a/test/pdf_scroll_bench.zig b/test/pdf_scroll_bench.zig index 33dfe70a..a4511dbe 100644 --- a/test/pdf_scroll_bench.zig +++ b/test/pdf_scroll_bench.zig @@ -42,6 +42,11 @@ //! //! Setup, teardown, checksumming, and reporting are outside every timer. const std = @import("std"); +const bench_util = @import("bench_util.zig"); +const nowNs = bench_util.nowNs; +const fatal = bench_util.Fatal("pdf-scroll-bench").f; +const mix = bench_util.mix; +const drainEffects = bench_util.drainEffects; const libc = std.c; const pardes = @import("pardes"); const pdf = @import("mupdf"); @@ -211,14 +216,6 @@ fn parseArgs(args: []const []const u8) Config { return config; } -fn parseCount(flag: []const u8, text: []const u8) usize { - const value = std.fmt.parseUnsigned(usize, text, 10) catch - fatal("{s} expects a positive integer", .{flag}); - if (value == 0 or value > 10_000) - fatal("{s} must be in 1..10000", .{flag}); - return value; -} - const Travel = struct { /// Scrollable display pixels: the whole strip minus one screenful. max_scroll: f64, @@ -520,20 +517,6 @@ fn stridedHash(seed: u64, rgba: []const u8) u64 { return hash; } -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)); -} - -fn drainEffects(core: *pardes.Pardes) void { - while (core.nextEffect()) |_| {} -} - fn verifyIdentity( name: []const u8, expected: *?Identity, @@ -557,13 +540,6 @@ fn verifyIdentity( } else expected.* = got; } -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)); -} - fn reportText(config: Config, travel: Travel, results: []const Result) void { std.debug.print("pardes PDF fast-scroll benchmark ({s})\n", .{bench_config.core_optimize}); std.debug.print( @@ -649,13 +625,12 @@ fn reportJson(io: std.Io, config: Config, travel: Travel, results: []const Resul std.Io.File.stdout().writeStreamingAll(io, out.buffered()) catch {}; } -fn fatal(comptime format: []const u8, args: anytype) noreturn { - std.debug.print("pdf-scroll-bench: " ++ format ++ "\n", args); - std.process.exit(1); -} - comptime { // The bench links the real MuPDF wrapper the core uses; keep the import // load-bearing so a build that silently dropped it fails here. _ = pdf.Document; } + +fn parseCount(flag: []const u8, text: []const u8) usize { + return bench_util.parsePositive(fatal, flag, text, 10_000); +} -- cgit v1.3