mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-08-02 05:39:05 +00:00
Profiling escape-heavy streams showed the dominant remaining cost was Parser.next: every byte routed through it copies a [3]?Action return value that is ~240 bytes (the action union is sized by osc.Command). A typical CSI sequence paid this twice: once for the first byte after "ESC [" (csi_entry has no fast path, so even the first parameter digit went through the table machine) and once for the final byte that dispatches the sequence. This extends the existing stream fast paths to cover both. The csi_param fast path now handles final bytes (0x40-0x7E) by finalizing parameters and dispatching the CSI directly via a new csiDispatchFinal, which replicates the parser's csi_dispatch action (MAX_PARAMS overflow drop, trailing parameter finalization, and the colon-separator validation for non-'m' finals) without constructing the action array. A new csi_entry fast path handles the byte right after "ESC [": first parameter digit, empty first parameter, private markers (0x3C-0x3F), and parameterless finals. Everything else (C0 controls, intermediates, the csi_entry colon edge case) still defers to the state machine. Because these paths dispatch without going through Parser.next, they would bypass a handler's vtRaw hook, so they are disabled at comptime for handlers that declare one (the inspector). Those handlers keep the exact previous behavior. Throughput measured with ghostty-bench terminal-stream (full terminal handler, 100 MB deterministic corpora, 120x80, M4 Max, ReleaseFast, hyperfine means of 10 runs). The csi corpus is a realistic mix of SGR, cursor movement, erases, and mode changes with short text runs; sgr is a doom-fire-like stream of truecolor SGRs and cell pairs: | stream | before | after | change | |--------|--------|--------|--------| | csi | 618 ms | 525 ms | +18% | | sgr | 486 ms | 414 ms | +17% |