mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-10 19:29:37 +00:00
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.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user