Skip to content

tui: render pin tiles at the parser's current size (fix split+pin lag)#390

Merged
edwin-zvs merged 1 commit into
mainfrom
fix-pin-split-thrash
Jun 7, 2026
Merged

tui: render pin tiles at the parser's current size (fix split+pin lag)#390
edwin-zvs merged 1 commit into
mainfrom
fix-pin-split-thrash

Conversation

@edwin-zvs

Copy link
Copy Markdown
Contributor

Problem

The TUI becomes extremely laggy when a split view and the pin strip are shown together — but it's fine with either alone.

Cause

A pinned session that's also visible in a split pane shares one cached vt100 parser per ItemHistory between the main render and the pin tile. replay resizes that parser to the requested dims, and a width change rebuilds it (re-feeds the pending chunk through a freshly-sized grid).

  • The main/split render sizes the parser to the split pane's width.
  • The pin tile then replayed the same parser at app.terminal_pane_size (the whole-view width).

Two different widths on the same parser each frame → two rebuilds per frame. Measured at ~45,000× the cost of a no-op resize on a long history (≈2 ms per session per frame). A few pinned-and-split sessions blow the frame budget.

The code already documented this exact thrash and "fixed" it by rendering the pin at the single main view size — which was safe when there was one main view. Split view gives each pane its own width, re-breaking the assumption.

stable width (no-op):        1 µs / 20 frames
alternating split/pin width: 45,146 µs / 20 frames   (~45000x)

Fix

The pin tile renders at the parser's current cached_dims() — the width the main/split render already set this frame — so its replay is a no-op resize and the parser is never rebuilt. Falls back to the main-view size only to seed a session with no cached parser yet (pin-only, never opened in the main view). cached_dims() is un-gated from cfg(test).

The invariant: not "render the pin at a fixed size" but "render the pin at whatever size the main render already set" — which holds for any number of split panes. See specs/0025-pin-tiles-share-the-main-parser-at-one-size.md.

Testing

  • New regression test pin_tile_reuses_cached_size_to_avoid_split_thrash — asserts the cached-size reuse is >10× faster than the forced-width thrash (machine-verified the cause and the fix).
  • cargo test -p agentd-cli pty_render (83) + pin (15) green; full workspace builds clean.
  • Worth a real check on your end: open a split view with pinned sessions and confirm the lag is gone.

🤖 Generated with Claude Code

The TUI is extremely laggy when a split view and the pin strip are
shown together, but fine with either alone.

Cause: a pinned session that is also visible in a split pane shares one
cached vt100 parser between the main render and the pin tile. The main
render sizes that parser to the split pane's width; the pin tile then
replayed it at app.terminal_pane_size (the whole-view width). Replaying
the same parser at two different widths each frame rebuilds it twice
per frame -- measured ~45000x the cost of a no-op resize on a long
history (~2ms/session/frame). A few such sessions blow the frame budget.

An earlier fix pinned the tile to the single 'main view' size, which was
safe when there was one main view. Split view gives each pane its own
width, re-breaking it.

Fix: the pin tile renders at the parser's current cached_dims() -- the
width the main/split render already set this frame -- so its replay is a
no-op resize. Falls back to the main-view size only to seed a session
with no cached parser yet. Un-gates cached_dims() from cfg(test).

Adds pin_tile_reuses_cached_size_to_avoid_split_thrash regression test.
Spec 0025.
@edwin-zvs
edwin-zvs merged commit 72cbe95 into main Jun 7, 2026
1 check passed
@edwin-zvs
edwin-zvs deleted the fix-pin-split-thrash branch June 7, 2026 19:14
@edwin-zvs edwin-zvs mentioned this pull request Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant