From bed47168ca7f34fe0a27e9f13c46b8df97cb77ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=92riks=20Remess?= Date: Tue, 7 Jul 2026 20:24:06 +0300 Subject: [PATCH] termio: bound POSIX read-ahead on non-Darwin The pipelined POSIX pty reader uses multiple large gather buffers to avoid stalling on Darwin, where pty reads are capped around 1KiB. On Linux this can let bulk terminal producers run too far ahead of terminal parsing/rendering. Frame-style terminal apps such as DOOM-fire can then report very high producer FPS while Ghostty displays stale frames from the buffered stream. Keep the Darwin-tuned 4 x 64KiB pipeline, but reduce non-Darwin read-ahead to 2 x 8KiB so the pty can apply backpressure before multiple frames are queued. --- src/termio/Exec.zig | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/termio/Exec.zig b/src/termio/Exec.zig index 42e2ffe78..8efcc73ec 100644 --- a/src/termio/Exec.zig +++ b/src/termio/Exec.zig @@ -1281,15 +1281,21 @@ pub const ReadThread = struct { /// stages. The gather stage can run at most this many batches /// ahead of the parse stage before it blocks, which (via the /// kernel pty queue) is also what preserves flow control to the - /// child. Empirically chosen through measurements on an M4 Max. - /// Less than 4 there are minor slowdowns, above 4 there are no - /// improvements. - const buffer_count = 4; + /// child. + /// + /// The Darwin value was empirically chosen through measurements on + /// an M4 Max. Less than 4 there are minor slowdowns, above 4 there + /// are no improvements. + /// + /// Other POSIX platforms keep fewer batches in flight so terminal + /// parsing applies backpressure to bulk writers before frame-style + /// output can queue stale frames. + const buffer_count = if (builtin.os.tag.isDarwin()) 4 else 2; /// The capacity of each gather buffer. One batch is also the unit /// of work the parse stage does per terminal lock acquisition, so /// this bounds both gather latency and lock hold time. - const buffer_capacity = 64 * 1024; + const buffer_capacity = if (builtin.os.tag.isDarwin()) 64 * 1024 else 8 * 1024; /// How many gathered bytes mark a stream as saturated. The macOS /// kernel tty output queue hands the master at most about 1 KiB