From cee35cabf69d9cf2501c945fe6ee23811552b024 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 6 Jul 2026 06:25:23 -0700 Subject: [PATCH] terminal: skip style map update when SGR leaves style unchanged Profiling the csi benchmark showed ~20% of time in the style ref-counted set (hash, probe, release/use churn) driven by manualStyleUpdate, which runs after every SGR attribute even when the attribute didn't actually change the cursor style. Real programs re-assert the same style constantly (per span, per line, or on every refresh of a mostly static screen), so a large share of these updates are no-ops. Screen.setAttribute already snapshots the old style to restore it on failure, so this compares the style after applying the attribute and returns early when it's unchanged: the current style ID is already correct and no release/lookup/use is needed. The tradeoff is one extra Style.eql on every style-changing attribute. Measured with ghostty-bench terminal-stream (full terminal handler, 100 MB deterministic corpora, 120x80, M4 Max, ReleaseFast, hyperfine means of 10 runs) across corpora with different repeated style rates (the csi/sgr corpora draw random colors from a palette so nearly every SGR changes the style, which is the worst case for this change; the redraw corpora model TUI refreshes that re-assert the current style for 70% / 95% of SGRs): | stream | before | after | change | |---------------------|--------|--------|--------| | redraw (95% same) | 277 ms | 260 ms | +7% | | redraw (70% same) | 302 ms | 291 ms | +4% | | csi (~0% same) | 407 ms | 414 ms | -2% | | sgr (~0% same) | 295 ms | 303 ms | -3% | Real-world SGR traffic is far closer to the redraw corpora than to the adversarial random-color ones, so this trades a small worst case regression for a solid win on the common pattern. --- src/terminal/Screen.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index 5c39be02f..c9cabfd27 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -1992,6 +1992,12 @@ pub fn setAttribute( .unknown => return, } + // If the attribute didn't change our style then we can skip the + // style update entirely: our current style ID is already correct. + // This is a common case in the wild where programs re-assert the + // same style repeatedly (e.g. per span or per line). + if (self.cursor.style.eql(old_style)) return; + try self.manualStyleUpdate(); }