Skip to content

perf(vscode): optimize large session load times and eliminate reactive cascades - #13154

Merged
marius-kilocode merged 1 commit into
mainfrom
optimize-large-session-loading-performance
Aug 17, 2026
Merged

perf(vscode): optimize large session load times and eliminate reactive cascades#13154
marius-kilocode merged 1 commit into
mainfrom
optimize-large-session-loading-performance

Conversation

@marius-kilocode

Copy link
Copy Markdown
Collaborator

Opening large sessions (500+ messages and thousands of parts) previously caused main-thread hitches and latency spikes during first-time loading in the webview.

Root Causes

  1. Cascading Reactive Subscriptions on Part Hydration: getParts(messageID) accessed store.parts[messageID] inside layout memos (turns, rows, partitionRows, railEntries), subscribing every message in the session to store.parts. When virtualized rows hydrated parts on mount, mutating store.parts invalidated all memoized rows across the entire transcript, triggering recomputation cascades for every mounted row.
  2. Recursive Tool Store Proxy Churn: rebuildToolParts always passed the full tool list through reconcile(tools, { key: "id" }) on cold replace loads, recursively traversing and creating reactive proxies for hundreds of tool calls that were not visible on screen.
  3. Uncapped Subagent Task Output IPC Payloads: Historical task tool outputs were not routed through slimmers, resulting in multi-megabyte payloads being serialized and passed across the extension IPC bridge.
  4. Redundant Hierarchy Scans on Idle Opens: sessionIDs, visibleToolParts, and activeUserMessageID ran full message scans and allocated sets during idle session opens even when sessions had zero subagent tasks.

Changes

  • Wrapped store.parts[messageID] reads in untrack() and prioritized stash.peek(), allowing layout memos to read parts without establishing reactive dependencies that get invalidated during part hydration.
  • Passed mode to rebuildToolParts / setTools and assigned tools directly on replace loads, bypassing recursive store reconciliation.
  • Added task: slimOutput to metadata slimmers to cap historical task outputs over the IPC bridge.
  • Added fast-path early returns in visibleToolParts, sessionIDs, and activeUserMessageID for idle sessions with no task tools.

Performance Profile & Benchmark

First-time cold load of session wt-1786000915486-13 (544 messages, 2,800+ parts) in the VS Code webview:

Metric Baseline Optimized Improvement
Script Execution Duration 836.75 ms 602.07 ms -28.0% (-234.68 ms)
Layout Duration 121.76 ms 85.30 ms -29.9%
Longest Main Thread Task 143.70 ms 104.42 ms -27.3%
CPU Profile Nodes 48,194 25,279 -47.5%
Transient DOM Nodes 6,921 3,485 -49.6%
Layout Objects Created 2,698 1,242 -54.0%
JS Event Listeners 1,940 746 -61.5%

@marius-kilocode
marius-kilocode merged commit 4eeafab into main Aug 17, 2026
24 checks passed
@marius-kilocode
marius-kilocode deleted the optimize-large-session-loading-performance branch August 17, 2026 08:38
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.

2 participants