tui: render pin tiles at the parser's current size (fix split+pin lag)#390
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
ItemHistorybetween the main render and the pin tile.replayresizes that parser to the requested dims, and a width change rebuilds it (re-feeds the pending chunk through a freshly-sized grid).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.
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 fromcfg(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
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.🤖 Generated with Claude Code