// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie // SPDX-License-Identifier: MIT //! Benchmark comparing the SIMD and scalar implementations of //! `computeCheckDigit`. Run with `zig build bench`. const std = @import("std"); const ISBN = @import("isbn").ISBN; const iterations = 50_000_000; const num_samples = 1024; fn makeSamples(random: std.Random, comptime field: []const u8, comptime n: usize) [num_samples]ISBN { var samples: [num_samples]ISBN = undefined; for (&samples) |*x| { var buf: [n]u8 = undefined; for (&buf) |*c| c.* = '0' + random.uintLessThan(u8, 10); x.* = @unionInit(ISBN, field, buf); } return samples; } fn bench(io: std.Io, comptime simd: bool, samples: *const [num_samples]ISBN) u64 { var sum: u64 = 0; const start: std.Io.Clock.Timestamp = .now(io, .awake); for (0..iterations) |i| { sum +%= samples[i & (num_samples - 1)].computeCheckDigitWith(simd); } const elapsed = start.untilNow(io); std.mem.doNotOptimizeAway(sum); return @intCast(elapsed.raw.nanoseconds); } fn report(comptime label: []const u8, simd_ns: u64, scalar_ns: u64) void { const simd_per_op = @as(f64, @floatFromInt(simd_ns)) / iterations; const scalar_per_op = @as(f64, @floatFromInt(scalar_ns)) / iterations; std.debug.print( "{s}: simd {d:.2} ns/op, scalar {d:.2} ns/op, speedup {d:.2}x\n", .{ label, simd_per_op, scalar_per_op, scalar_per_op / simd_per_op }, ); } pub fn main() void { var threaded: std.Io.Threaded = .init(std.heap.page_allocator, .{}); defer threaded.deinit(); const io = threaded.io(); var prng = std.Random.DefaultPrng.init(0xbadc0ffee); const random = prng.random(); const tens = makeSamples(random, "10", 10); const thirteens = makeSamples(random, "13", 13); report( "ISBN-10", bench(io, true, &tens), bench(io, false, &tens), ); report( "ISBN-13", bench(io, true, &thirteens), bench(io, false, &thirteens), ); }