From caf9405db0eeebc31cf3bdcebae96f8da938ddec Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 5 Feb 2024 13:36:46 -0800 Subject: [PATCH] bench/stream: add terminal option --- bench.sh | 9 ++++--- src/bench/stream.zig | 57 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/bench.sh b/bench.sh index 5cd693a13..323fda5f9 100755 --- a/bench.sh +++ b/bench.sh @@ -5,11 +5,14 @@ SIZE="25M" +# Uncomment to test with an active terminal state. +#ARGS=" --terminal" + hyperfine \ --warmup 10 \ -n memcpy \ - "./zig-out/bin/bench-stream --mode=gen-ascii | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=noop" \ + "./zig-out/bin/bench-stream --mode=gen-ascii | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=noop${ARGS}" \ -n scalar \ - "./zig-out/bin/bench-stream --mode=gen-ascii | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=scalar" \ + "./zig-out/bin/bench-stream --mode=gen-ascii | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=scalar${ARGS}" \ -n simd \ - "./zig-out/bin/bench-stream --mode=gen-ascii | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=simd" + "./zig-out/bin/bench-stream --mode=gen-ascii | head -c ${SIZE} | ./zig-out/bin/bench-stream --mode=simd${ARGS}" diff --git a/src/bench/stream.zig b/src/bench/stream.zig index d0f53e504..28156a9e0 100644 --- a/src/bench/stream.zig +++ b/src/bench/stream.zig @@ -18,6 +18,13 @@ const terminal = @import("../terminal/main.zig"); const Args = struct { mode: Mode = .noop, + /// Process input with a real terminal. This will be MUCH slower than + /// the other modes because it has to maintain terminal state but will + /// help get more realistic numbers. + terminal: bool = false, + @"terminal-rows": usize = 80, + @"terminal-cols": usize = 120, + /// This is set by the CLI parser for deinit. _arena: ?ArenaAllocator = null, @@ -66,11 +73,39 @@ pub fn main() !void { const reader = std.io.getStdIn().reader(); const writer = std.io.getStdOut().writer(); + + // Handle the modes that do not depend on terminal state first. switch (args.mode) { .@"gen-ascii" => try genAscii(writer), .noop => try benchNoop(alloc, reader), - .scalar => try benchScalar(alloc, reader), - .simd => try benchSimd(alloc, reader), + + // Handle the ones that depend on terminal state next + inline .scalar, + .simd, + => |tag| { + if (args.terminal) { + const TerminalStream = terminal.Stream(*TerminalHandler); + var t = try terminal.Terminal.init( + alloc, + args.@"terminal-cols", + args.@"terminal-rows", + ); + var handler: TerminalHandler = .{ .t = &t }; + var stream: TerminalStream = .{ .handler = &handler }; + switch (tag) { + .scalar => try benchScalar(alloc, reader, &stream), + .simd => try benchSimd(alloc, reader, &stream), + else => @compileError("missing case"), + } + } else { + var stream: terminal.Stream(NoopHandler) = .{ .handler = .{} }; + switch (tag) { + .scalar => try benchScalar(alloc, reader, &stream), + .simd => try benchSimd(alloc, reader, &stream), + else => @compileError("missing case"), + } + } + }, } } @@ -115,12 +150,9 @@ fn benchNoop(alloc: Allocator, reader: anytype) !void { std.log.info("total bytes len={}", .{total}); } -fn benchScalar(alloc: Allocator, reader: anytype) !void { +fn benchScalar(alloc: Allocator, reader: anytype, stream: anytype) !void { _ = alloc; - // Create a stream that uses our noop handler so we don't - // have any terminal state overhead. - var stream: terminal.Stream(NoopHandler) = .{ .handler = .{} }; var buf: [4096]u8 = undefined; while (true) { const n = try reader.read(&buf); @@ -132,10 +164,9 @@ fn benchScalar(alloc: Allocator, reader: anytype) !void { } } -fn benchSimd(alloc: Allocator, reader: anytype) !void { +fn benchSimd(alloc: Allocator, reader: anytype, stream: anytype) !void { _ = alloc; - var stream: terminal.Stream(NoopHandler) = .{ .handler = .{} }; var buf: [4096]u8 = undefined; while (true) { const n = try reader.read(&buf); @@ -145,8 +176,16 @@ fn benchSimd(alloc: Allocator, reader: anytype) !void { } const NoopHandler = struct { - fn print(self: NoopHandler, cp: u21) !void { + pub fn print(self: NoopHandler, cp: u21) !void { _ = self; _ = cp; } }; + +const TerminalHandler = struct { + t: *terminal.Terminal, + + pub fn print(self: *TerminalHandler, cp: u21) !void { + try self.t.print(cp); + } +};