Symptom
When scrolling back through a long transcript (lots of streamed text + tool calls), the whole TUI becomes sluggish — every keypress and frame is visibly delayed. The lag scales with how far back the user has scrolled, suggesting an O(N) (or worse) recomputation per render.
Reproduced today on a session with a few minutes of dense streamed content; scrolling to the top made every subsequent keypress feel like ~200–500ms behind.
Suspected root cause
Transcript rendering likely re-wraps and re-styles every history item from the start of the buffer on each frame, instead of:
- Caching wrapped `Vec<Line<'_>>` per history item, invalidated only on resize / item edit.
- Computing the visible window's start by walking from a maintained scroll-offset cursor rather than re-folding from `history[0]`.
- Skipping items entirely above the viewport.
Worth profiling before fixing — `samply` on macOS or the simpler `std::time::Instant` around `render_transcript` would tell us which loop is hot.
Reference
Codex's transcript widget caches per-item wrapped lines and only re-wraps on resize. See `/Volumes/VIXinSSD/codex-main/codex-rs/tui/src/chatwidget.rs` for the pattern (cached `HistoryCell` items + viewport-clipped iteration).
Plan
- Profile a representative "long-scroll" session — capture wall-clock per render frame at scroll offsets 0, 100, 500, 2000.
- If `render_transcript` (or whatever the equivalent in `crates/tui/src/tui/ui.rs` / `tui/transcript.rs`) shows linear growth: add per-item wrapped-line cache keyed on (item id, terminal width).
- Skip items entirely above the viewport during render iteration.
- Add a regression test: build a 5,000-item transcript, render at scroll offset `history.len() - 30`, assert render time < some bound (e.g. 16ms on a baseline machine — or just assert the per-item cost is bounded vs the offset).
Acceptance
- Scrolling back through a 1,000-message transcript stays under ~50ms per frame on baseline hardware.
- Keypress latency at any scroll offset is dominated by user input → event-loop hop, not render.
Symptom
When scrolling back through a long transcript (lots of streamed text + tool calls), the whole TUI becomes sluggish — every keypress and frame is visibly delayed. The lag scales with how far back the user has scrolled, suggesting an O(N) (or worse) recomputation per render.
Reproduced today on a session with a few minutes of dense streamed content; scrolling to the top made every subsequent keypress feel like ~200–500ms behind.
Suspected root cause
Transcript rendering likely re-wraps and re-styles every history item from the start of the buffer on each frame, instead of:
Worth profiling before fixing — `samply` on macOS or the simpler `std::time::Instant` around `render_transcript` would tell us which loop is hot.
Reference
Codex's transcript widget caches per-item wrapped lines and only re-wraps on resize. See `/Volumes/VIXinSSD/codex-main/codex-rs/tui/src/chatwidget.rs` for the pattern (cached `HistoryCell` items + viewport-clipped iteration).
Plan
Acceptance