From 4c5b1d5d52a5c8a79be2db897c8fbddaad64f1d2 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 6 Jul 2026 12:25:19 -0700 Subject: [PATCH] bench: terminal-stream reads 64KiB chunks to match the IO thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The terminal-stream benchmark fed the stream in 4KiB chunks while the real IO thread reads from the pty into 64KiB buffers (see buffer_capacity in termio/Exec.zig) and hands those to the stream whole. Chunk size affects measurement in two ways: it determines how often the stream crosses a chunk boundary (partial UTF-8 sequences, escape sequences split mid-parse) and how many read syscalls the harness itself performs (a 2.6 GB corpus is ~636k pread calls at 4KiB versus ~40k at 64KiB). This bumps the benchmark read and dispatch buffers to 64KiB so the stream is exercised with realistic chunk sizes. Measured with ghostty-bench terminal-stream on a 2.6 GB recording of real terminal sessions (120x80, M4 Max, ReleaseFast, hyperfine means): | harness | time | throughput | |--------------|-----------------|------------| | 4KiB chunks | 9.651 s ± 0.013 | 270 MB/s | | 64KiB chunks | 9.582 s ± 0.101 | 272 MB/s | The stream itself is barely chunk-size sensitive (most time is in parsing and terminal state updates), but the harness now matches what the IO thread actually does, and later commits are measured against this configuration. --- src/benchmark/TerminalStream.zig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/benchmark/TerminalStream.zig b/src/benchmark/TerminalStream.zig index e0cab9033..a5302005b 100644 --- a/src/benchmark/TerminalStream.zig +++ b/src/benchmark/TerminalStream.zig @@ -112,11 +112,14 @@ fn step(ptr: *anyopaque) Benchmark.Error!void { // aren't currently IO bound. const f = self.data_f orelse return; - var read_buf: [4096]u8 align(std.atomic.cache_line) = undefined; + var read_buf: [64 * 1024]u8 align(std.atomic.cache_line) = undefined; var f_reader = f.reader(&read_buf); const r = &f_reader.interface; - var buf: [4096]u8 = undefined; + // This buffer size matches the read buffer size used by the + // real IO thread (see termio Exec.zig buffer_capacity) so that + // the benchmark exercises the stream with realistic chunk sizes. + var buf: [64 * 1024]u8 = undefined; while (true) { const n = r.readSliceShort(&buf) catch { log.warn("error reading data file err={?}", .{f_reader.err});