Skip to content

[Improve] Reduce chat memory retained during long sessions - #2217

Open
zoomote2[bot] wants to merge 8 commits into
mainfrom
feature/webview-memory-optimization-1466
Open

zoomote2[bot] wants to merge 8 commits into
mainfrom
feature/webview-memory-optimization-1466

Conversation

@zoomote2

@zoomote2 zoomote2 Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

​Created by Roomote. View the session.

Copy of #1466 (original author account was deleted). Original work by @taltas — see the original PR for prior discussion and review comments.

What changed

  • Intern repeated strings in completed chat messages and task history. Bound each cache to 10,000 entries and 2,000,000 retained characters with FIFO eviction.
  • Skip partial messages and stale updates. Rebind equal strings in unchanged flat messages across state pushes while retaining the incoming message objects; messages with newly deserialized object or array fields still take the normal interning path.
  • Clear the message cache when the active task changes or is cleared, including when JSON serialization omits an undefined task ID. Rebuild the history cache when history is replaced.
  • Preserve task identity on stale pushes and on pushes without messages.
  • Keep cache writes outside React state updaters. Preserve chat and row instances across task changes and message completion.
  • Add focused coverage for cache routing, lifecycle, sequence boundaries, message-mirror synchronization, eviction limits, and row-instance preservation.

Why

State broadcasts repeatedly deserialize message and history strings. Sharing equal strings reduces retained allocations within a transcript and across successive snapshots. The cache limits bound its own retention; clearing a cache does not guarantee that other UI references release the same messages.

Heap measurements

Measured in real VS Code 1.100.0 under Xvfb using CDP forced GC on the Zoo Code webview renderer. Each workload loads a deterministic saved transcript of 602 UI messages, including 300 command/output pairs with 16.4–16.9 KiB outputs, then switches to a small task. A full-state refresh after hydration exercises sharing across broadcasts.

Three fresh measurement sessions per workload and variant produced 12 successful samples. The extension host, dependencies and styles are held constant; both webview builds use production minification without source maps. External downloads are blocked during the workload, and seed tasks use a local mock model.

Median loaded renderer heap:

Workload Base Candidate Reduction
32 distinct outputs repeated across 300 commands 41.42 MiB 31.75 MiB 9.67 MiB (23%)
300 unique outputs 41.58 MiB 36.63 MiB 4.95 MiB (12%)

Base webview modules: 97228c7ca9b032e5fe466e57e24fe72fbf405192. Candidate: b9a6ba03cb93c0f92f06cfb00c82ae7d488db7cb.

These are historical measurements of the recorded revisions and have not been rerun for the review fixes. Repeated outputs benefit from cache interning; unchanged strings are also shared across snapshots after FIFO eviction, which helps the unique workload. The comparison does not isolate each mechanism’s contribution.

These replace the earlier standalone synthetic 8.6 MiB estimate. The new measurements exercise the real extension/webview path with generated saved-task data; they are not an organic user session and do not measure CPU overhead, image-rich messages, continuously streamed execution, extension-host heap, or process RSS.

Task-switch finding

All six candidate post-switch snapshots contain zero old output strings in the StringCache maps. Old output strings remain reachable elsewhere in both base and candidate. An inspected strong retaining path runs through React props and onJumpToPreviousCheckpoint callback closure contexts into an old message array.

Cache cleanup is confirmed, but complete task-memory release is not. Investigating that existing callback retention remains a follow-up; these snapshots do not establish indefinite growth. Chat behavior and appearance are unchanged, and no forced remounts are introduced.

Validation and artifacts

  • Four focused webview suites: 108 tests pass; webview type checking and ESLint pass without increased suppressions.
  • Heap benchmark: 12 successful samples and 36 snapshots. One setup attempt using an earlier readiness check was excluded and successfully rerun.
  • Benchmark package type checking and ESLint pass.
  • The opt-in benchmark harness and results report are included in this PR under apps/vscode-e2e/src/heap/; raw snapshots, measurements and retaining-path evidence are gitignored under apps/vscode-e2e/heap-results/.

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one): 1
  • coderabbit-review-active

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@zoomote2

zoomote2 Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor Author

No new code issues found. See session

Re-reviewed the new commit 2ff4aa6 ("Address webview memory optimization review feedback") on top of the previously reviewed 5ba6d60:

  • The messagesAreStale and internMessages extractions in ExtensionStateContext.tsx are behavior-preserving refactors of the inline logic verified last round, and the messageUpdated mirror now uses findLastIndex, aligning it with the React state update path (this fixes a first-vs-last duplicate-ts inconsistency in the mirror).
  • New tests cover initial/current-task history interning, keys dropped by JSON snapshots, duplicate-timestamp mirror updates, stale-task-push cache preservation, FIFO non-refresh on cache hits, and null/undefined interning; assertions match the implementation's actual semantics.
  • The heap harness changes (prepare.ts base variant now reverting only ExtensionStateContext.tsx, test.info() usage) are consistent with the updated README/RESULTS, which now clearly disclose that the recorded measurements are historical and not rerun for these fixes.
  • The earlier note about the PR description is resolved — the Validation section now correctly states the harness and results report are committed in this PR.

CI at this head: compile, codecov patch checks (including webview-patch), knip, translations, and VSIX build pass; remaining unit/visual/e2e jobs were still running at review time.

Previously reviewed at 5ba6d60 — string interning (stringCache.ts) and the cache lifecycle / task-identity guards in ExtensionStateContext.tsx, plus the tests and the opt-in heap benchmark under apps/vscode-e2e/src/heap/:

Reviewed 31e260a

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Review status

This PR was opened by an automated account. A human maintainer must verify the change intent, provenance, and validation before merging.

Current step: Awaiting fresh human maintainer or CODEOWNER approval.

Review-state labels are managed by this workflow; do not edit them manually. community-approved is managed the same way — do not add or remove it manually. It signals a fresh community code approval for the current head as an advisory priority only; maintainer review is still required.

@edelauna
edelauna marked this pull request as ready for review October 28, 2026 03:56
@codecov

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.91304% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
webview-ui/src/utils/stringCache.ts 97.29% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot added the awaiting-maintainer CodeRabbit approved; waiting for a human maintainer label Oct 28, 2026
@github-actions github-actions Bot added awaiting-maintainer CodeRabbit approved; waiting for a human maintainer and removed awaiting-maintainer CodeRabbit approved; waiting for a human maintainer labels Oct 28, 2026
@github-actions github-actions Bot added the community-approved Fresh community approval on the current head; maintainer review still required label Oct 29, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-maintainer CodeRabbit approved; waiting for a human maintainer community-approved Fresh community approval on the current head; maintainer review still required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants