perf(mobile): bound the parsed review cache - #9749
Conversation
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a contained mobile performance change that bounds parsed review-diff retention and optional prewarming without changing the rendered review results or introducing a new capability. Focused tests cover LRU eviction, source budgets, reset behavior, and reuse of parsed/native results. You can add or adjust custom eligibility rules. Learn more. |
## What's Changed * perf(server): use one query for buffered provider events by @t3dotgg in pingdotgg/t3code#9706 * perf(relay): avoid repeated activity decoding by @t3dotgg in pingdotgg/t3code#9708 * perf(web): stop continuous chat status animations by @t3dotgg in pingdotgg/t3code#9709 * fix(mobile): preserve saved work after storage read failures by @t3dotgg in pingdotgg/t3code#9710 * perf(web): stop replaying terminal buffers on rollover by @t3dotgg in pingdotgg/t3code#9707 * feat(web): preview pull request links by @maria-rcks in pingdotgg/t3code#9631 * perf(client): reduce thread-list update work by @t3dotgg in pingdotgg/t3code#9716 * fix(server): settle inactive threads with open PRs by @Gigioxx in pingdotgg/t3code#9610 * fix(server): bound slow-client event buffers by @t3dotgg in pingdotgg/t3code#9715 * test(server): allow either valid file-search match by @t3dotgg in pingdotgg/t3code#9720 * fix(web): match provider settings layout for disconnected devices by @flamboh in pingdotgg/t3code#9619 * fix(web): keep the slash menu above the composer when vertical space is short by @Mnigos in pingdotgg/t3code#9625 * fix(mobile): remove provider setup by @juliusmarminge in pingdotgg/t3code#9721 * perf(web): stop rendering hidden terminals by @t3dotgg in pingdotgg/t3code#9718 * fix(mobile): read file-backed image drafts before enabling them by @t3dotgg in pingdotgg/t3code#9713 * perf(server): replay only the selected thread by @t3dotgg in pingdotgg/t3code#9726 * fix(web): mute composer helper text by @jakeleventhal in pingdotgg/t3code#9654 * feat(web): unpin threads from the sidebar multi-select menu by @gsimone in pingdotgg/t3code#9651 * perf(web): reuse timeline rows while text streams by @t3dotgg in pingdotgg/t3code#9725 * fix(relay): bound stalled push requests by @t3dotgg in pingdotgg/t3code#9734 * perf(server): stop caching unused OpenCode tool parts by @t3dotgg in pingdotgg/t3code#9738 * fix(web): fold single trailing activity by @maria-rcks in pingdotgg/t3code#9739 * fix(web): show project settings for new threads by @maria-rcks in pingdotgg/t3code#9743 * perf(mobile): bound the parsed review cache by @t3dotgg in pingdotgg/t3code#9749 **Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260904.1279...v0.0.39-nightly.20260904.1280 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260904.1280
Mobile review keeps every parsed diff and its native rows until the app registry resets. Opening more sections keeps adding memory.
The cache now keeps up to eight entries and 4,194,304 source characters. Nearby prewarming uses the same budget and reserves room for the selected section. Oversized diffs are not cached or prewarmed. Current view references and row IDs stay valid.
In a Node source proof with 64 sections, retained parsed diffs and prepared native row sets each fall from 64 to 8. The retained heap delta falls from 47.9 MB to 10.7 MB. In the 10-section prewarming proof, switching between the first two sections adds no parses after warmup. These are not device measurements.
M6 in the performance audit remains partial. Raw patches, drafts, comments, and preferences are unchanged. The source-character limit is not an exact heap-byte limit.
Verified with 31 focused tests, mobile typecheck, targeted lint, and real-source GC and prewarming proofs. No native code changed. No browser, device, or native build verification ran.
Created with GPT-6 Astra (preview) in Codex.
Note
Medium Risk
Changes review diff caching and idle prewarming semantics; wrong eviction or budget accounting could cause extra parses or stale assumptions, but behavior is heavily tested and scoped to mobile review performance.
Overview
Bounds mobile review parsed-diff memory by replacing unbounded per-section atom caches with a single LRU store capped at 8 sections and 4 MiB of raw diff source (not parsed/native heap).
getCachedReviewParsedDiffnow tracks source length, evicts oldest entries when limits are hit, skips caching oversized patches (still returns a fresh parse), and clears onappAtomRegistry.reset. Whitespace-trimmed hits refresh LRU order; content changes reclaim budget for that section.Prewarming no longer warms every other loaded section.
getReviewDiffPrewarmSectionspicks nearest neighbors that fit the shared entry and character budget (reserving the selected section, including when cached source was retained with trailing whitespace).prewarmReviewDiffSectionbails on null or oversized diffs without parsing.New unit tests cover LRU across threads, source-budget eviction/reclaim, oversized behavior, registry reset, and prewarm selection/reuse.
Reviewed by Cursor Bugbot for commit 0369853. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Bound parsed review diff cache to 8 entries and 4 MiB source budget
getReviewParsedDiffSourceCharacterCountso prewarming callers account for the full retained source length, including whitespace absent from an equivalent normalized inputuseReviewDiffPrewarmingto plan prewarming of at most 7 loaded neighboring sections ordered by distance from the selection, skipping neighbors that exceed the remaining source budgetgetCachedReviewParsedDiffevicts oldest entries globally across thread keys when either the entry count or source budget is exceeded; callers expecting unbounded retention will see parsed results rebuilt on cache missesMacroscope summarized 0369853.