perf: close the last benchmark gaps to Zig (render state, parser)

- RenderState stores styles sparsely (per-cell u16 style ids plus one
  Style per distinct run) and skips plain cells with a single mask test
  (Cell::is_plain). screen-clone render: 11.5 ms -> 4.1 ms (Zig 4.7).
  row::never_extend_bg now takes a style accessor instead of a slice.
- Parser::next_with(byte, |action| ..) hands actions to a closure
  instead of moving a 64-byte action array out; Parser::next remains a
  wrapper over the same core (equivalence test added).
  terminal-parser SGR: 538 ms -> 231 ms (Zig 354).

All Ghostty benchmarks are now at or below Zig's time; table in
docs/rewrite/notes/perf-P1.md (the parser benchmark uses next_with with
a discarding closure, which like Zig's `_ = actions` lets the optimizer
skip unused work).

Test Plan:
- cargo test --workspace
- ghostty-bench +screen-clone --mode=render / +terminal-parser
This commit is contained in:
ddidderr committed 2026-10-12 05:22:01 +02:00
1 parent d89691b0ce
commit abb89a80e9
7 files changed
+177 -56

No files matched your search

+1 -1
View File
@@ -178,7 +178,7 @@ impl Benchmark for TerminalParser {
let mut p = Parser::new();
self.data.for_each_chunk(|chunk| {
for &c in chunk {
drop(p.next(c));
p.next_with(c, drop);
}
Ok(())
})