Skip to content

TUI: whole screen lags when scrolling far back in transcript #78

@Hmbown

Description

@Hmbown

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:

  1. Caching wrapped `Vec<Line<'_>>` per history item, invalidated only on resize / item edit.
  2. Computing the visible window's start by walking from a maintained scroll-offset cursor rather than re-folding from `history[0]`.
  3. 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

  1. Profile a representative "long-scroll" session — capture wall-clock per render frame at scroll offsets 0, 100, 500, 2000.
  2. 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).
  3. Skip items entirely above the viewport during render iteration.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions