Repository navigation
Reuse cached parser size when two split panes show one session - #658
Merged
Merged
Conversation
A stale window-selection reassignment — the neighbor a deleted or archived session's pane falls back to (focus_neighbor_of) — can leave two split panes showing the same session. ItemHistory caches a single parser sized to whichever width it was last replayed at; two panes at two different widths alternate that width every frame. For a plain PTY session this is a bounded-tail rebuild (cheap). For a tool-block session (smith/claude/codex — anything with a ToolBlock item), replay_full's cols-change path rebuilds from item 0 on every call: measured multiple seconds for just a couple thousand accumulated lines once cols alternate every call, versus near-instant when cols stay stable. Same failure family as pin_tile_reuses_cached_size_to_avoid_split_thrash, which already guards the split+pin-strip case — just never guarded two ordinary split panes converging on one session. render_terminal_for_window now reuses the first pane's cached parser size for any later pane rendering an already-replayed-this-frame session, trading a slightly-off-size duplicate render for avoiding the rebuild.
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.
Summary
Follow-up to #650 — that fix stopped the accumulation of stale Program state, but the user found the TUI still goes "extremely laggy, unusable" from a single occurrence of this concrete sequence:
Deleting/archiving #2 triggers
focus_neighbor_of, which reassigns #2's pane to its list neighbor — session #1. Both panes now show session #1.Root cause
ItemHistory(the per-session PTY/tool-block replay cache) holds a single cached parser sized to whichever width it was last asked to replay at. Two panes showing the same session at two different widths callhistory.replay(width, ...)with alternating widths every single frame — each call invalidates and rebuilds the cache the other pane just set.replay_cached), the rebuild is a bounded tail re-feed — cheap.ToolBlock),replay_full's cols-change path rebuilds from item 0 on every call. Measured: a couple thousand accumulated lines with alternating cols took multiple seconds per frame; a 50k-line real-world history didn't finish in over a minute. Stable cols, by contrast, is near-instant (existingreplay_full_scales_with_history_sizetest).This is the same failure family the existing
pin_tile_reuses_cached_size_to_avoid_split_thrashtest already guards against for the split+pin-strip case — it was just never guarded for two ordinary split panes converging on one session, which wasn't reachable before this delete/archive-neighbor-reassignment behavior existed.Fix
render_terminal_for_windownow tracks which sessions have already been replayed this frame (terminal_replayed_sessions_this_frame, cleared every frame). The first pane to render a session uses its own natural width as before. Any later pane rendering the same session this frame reuses the first pane'scached_dims()instead of forcing its own — so the cache never actually alternates. Trade-off: the duplicate pane's content may not perfectly fill its own width, which is a much better outcome than a multi-second-per-frame freeze.Test plan
two_split_panes_same_session_reuses_cached_size_instead_of_thrashing: two split panes at deliberately unequal widths show one tool-block session; asserts 30 frames stay under 1s. Verified it actually catches the regression (fails at ~2.7s with the fix disabled, passes at ~0.08s with it enabled).two_windows_converging_on_one_session_with_program_open: drives the realopen_program_popup/select_session/split_active_window/on_session_deletedmethods end-to-end and checks Program-popup bookkeeping stays consistent through the convergence.cargo test -p agentd-cli— 519 passed, 0 failed (including the pre-existingpin_tile_reuses_cached_size_to_avoid_split_thrashandreplay_full_scales_with_history_size).cargo build/cargo clippy -p agentd-cli --no-deps— no new warnings.