From 258de36d152522476b9f2443e9f37aad8cc6f79b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 6 Jul 2026 06:10:15 -0700 Subject: [PATCH] benchmark: terminal-stream uses the full terminal handler The terminal-stream benchmark previously used a simplified handler that handles print actions and drops everything else. That was originally intended to isolate parse and print throughput, but it understates the cost of escape-heavy streams: no terminal state is updated for CSI/OSC/ESC sequences, and because actions are dispatched at comptime, the unhandled action arms are eliminated entirely, so the benchmark measures dispatch code that doesn't exist in the real app. This switches the benchmark to the full readonly terminal stream handler (terminal.TerminalStream). Every escape sequence now updates real terminal state (styles, cursor movement, erases, modes, etc.), closely mirroring the work the real IO thread does per byte. This is the handler used to measure the VT throughput changes in the following commits. Parser-in-isolation measurement remains covered by the separate terminal-parser and osc-parser benchmarks, and print throughput is identical under both handlers since printing flows into the same Terminal call either way. --- src/benchmark/TerminalStream.zig | 42 ++++++++------------------------ 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/benchmark/TerminalStream.zig b/src/benchmark/TerminalStream.zig index 1cac656e2..e0cab9033 100644 --- a/src/benchmark/TerminalStream.zig +++ b/src/benchmark/TerminalStream.zig @@ -2,15 +2,13 @@ //! handler from input to terminal state update. This is useful to //! test general throughput of VT parsing and handling. //! -//! Note that the handler used for this benchmark isn't the full -//! terminal handler, since that requires a significant amount of -//! state. This is a simplified version that only handles specific -//! terminal operations like printing characters. We should expand -//! this to include more operations to improve the accuracy of the -//! benchmark. +//! This uses the full readonly terminal stream handler +//! (terminal.TerminalStream) so every escape sequence updates real +//! terminal state (styles, cursor movement, erases, modes, etc.). +//! This closely mirrors the work done by the real IO thread. //! -//! It is a fairly broad benchmark that can be used to determine -//! if we need to optimize something more specific (e.g. the parser). +//! For more isolated measurements see the terminal-parser and +//! osc-parser benchmarks. const TerminalStream = @This(); const std = @import("std"); @@ -20,13 +18,12 @@ const terminalpkg = @import("../terminal/main.zig"); const Benchmark = @import("Benchmark.zig"); const options = @import("options.zig"); const Terminal = terminalpkg.Terminal; -const Stream = terminalpkg.Stream(*Handler); +const Stream = terminalpkg.TerminalStream; const log = std.log.scoped(.@"terminal-stream-bench"); opts: Options, terminal: Terminal, -handler: Handler, stream: Stream, /// The file, opened in the setup function. @@ -61,14 +58,15 @@ pub fn create( .rows = opts.@"terminal-rows", .cols = opts.@"terminal-cols", }), - .handler = .{ .t = &ptr.terminal }, - .stream = .init(&ptr.handler), + .stream = undefined, }; + ptr.stream = .initAlloc(alloc, .init(&ptr.terminal)); return ptr; } pub fn destroy(self: *TerminalStream, alloc: Allocator) void { + self.stream.deinit(); self.terminal.deinit(alloc); alloc.destroy(self); } @@ -129,26 +127,6 @@ fn step(ptr: *anyopaque) Benchmark.Error!void { } } -/// Implements the handler interface for the terminal.Stream. -/// We should expand this to include more operations to make -/// our benchmark more realistic. -const Handler = struct { - t: *Terminal, - - pub fn vt( - self: *Handler, - comptime action: Stream.Action.Tag, - value: Stream.Action.Value(action), - ) void { - switch (action) { - .print => self.t.print(value.cp) catch |err| { - log.warn("error processing benchmark print err={}", .{err}); - }, - else => {}, - } - } -}; - test TerminalStream { const testing = std.testing; const alloc = testing.allocator;