Tabs: release detached Calendar page views after Tab switches #1356

Open
opened 2026-10-07 13:26:36 +00:00 by kayg · 2 comments
Owner

Found during the #1338 Tab storm investigation. Related: #1233.

A local production run completed three 120 second storms in one page. After forced GC, heap grew from 27,084,472 bytes after storm 1 to 33,130,784 bytes after storm 3 (+22.3%). DOM nodes grew from 12,344 to 26,205 (+112.3%). The host load was high, so the perf-VM run will confirm these memory and DOM results.

Heap snapshots show the strong retaining path through the SvelteKit client page-data reaction into the Calendar route page context, then #calendar-panel → .agenda → retained Calendar day rows. The route scope owns displayAgenda in apps/web/src/routes/calendar/[view]/[date]/+page.svelte:344, which derives a new CalendarDay.items array. The retained page scopes keep their detached DOM trees: two detached Calendar panels after storm 1 and ten after storm 3. The after-storm-3 snapshot retains an items array of 1,133 rows. The event-listener count fell from 1,087 to 970, so the evidence points to retained route state rather than a listener-count leak.

Please identify why a Calendar page scope stays reachable after leaving the Tab, then release its derived rows and DOM on route teardown. Add a repeated Tab-switch regression for the route lifetime.

The ignored local snapshots and trace are artifacts/tabstorm-1338/local-native-after-storm-1.heapsnapshot, artifacts/tabstorm-1338/local-native-after-storm-3.heapsnapshot and artifacts/tabstorm-1338/local-native-budget-failure-trace.json. They are not committed. The trace shows the slow app frames in Svelte's shared runtime chunk BIPLcumV.js; they are indicative on this host and do not identify a separate application function.

Found during the #1338 Tab storm investigation. Related: #1233. A local production run completed three 120 second storms in one page. After forced GC, heap grew from 27,084,472 bytes after storm 1 to 33,130,784 bytes after storm 3 (+22.3%). DOM nodes grew from 12,344 to 26,205 (+112.3%). The host load was high, so the perf-VM run will confirm these memory and DOM results. Heap snapshots show the strong retaining path through the SvelteKit client page-data reaction into the Calendar route page context, then `#calendar-panel` → `.agenda` → retained Calendar day rows. The route scope owns `displayAgenda` in `apps/web/src/routes/calendar/[view]/[date]/+page.svelte:344`, which derives a new `CalendarDay.items` array. The retained page scopes keep their detached DOM trees: two detached Calendar panels after storm 1 and ten after storm 3. The after-storm-3 snapshot retains an `items` array of 1,133 rows. The event-listener count fell from 1,087 to 970, so the evidence points to retained route state rather than a listener-count leak. Please identify why a Calendar page scope stays reachable after leaving the Tab, then release its derived rows and DOM on route teardown. Add a repeated Tab-switch regression for the route lifetime. The ignored local snapshots and trace are `artifacts/tabstorm-1338/local-native-after-storm-1.heapsnapshot`, `artifacts/tabstorm-1338/local-native-after-storm-3.heapsnapshot` and `artifacts/tabstorm-1338/local-native-budget-failure-trace.json`. They are not committed. The trace shows the slow app frames in Svelte's shared runtime chunk `BIPLcumV.js`; they are indicative on this host and do not identify a separate application function.
Author
Owner

Follow-up to the local finding: the perf VM did not reproduce a growing Calendar panel count. The after-storm-1 and after-storm-3 native snapshots each contain one detached #calendar-panel; the local snapshot comparison remains 2 → 10. Treat the source path below as a confirmed local retention path, not a VM-confirmed growth path.

The local heap retainer is the SvelteKit client page-data reaction → Calendar route scope → #calendar-panel → .agenda → CalendarDay.items, retained through displayAgenda in apps/web/src/routes/calendar/[view]/[date]/+page.svelte:344. The VM also retained detached Mail views, tracked separately in #1375.

VM snapshots and traces remain in ignored artifacts/tabstorm-1338/ as cpu4-after-storm-{1,3}.heapsnapshot and native-after-storm-{1,3}.heapsnapshot; the trace files are cpu4-budget-failure-trace.json and native-budget-failure-trace.json. They are not committed.

Follow-up to the local finding: the perf VM did not reproduce a growing Calendar panel count. The after-storm-1 and after-storm-3 native snapshots each contain one detached `#calendar-panel`; the local snapshot comparison remains 2 → 10. Treat the source path below as a confirmed local retention path, not a VM-confirmed growth path. The local heap retainer is the SvelteKit client page-data reaction → Calendar route scope → `#calendar-panel` → `.agenda` → `CalendarDay.items`, retained through `displayAgenda` in `apps/web/src/routes/calendar/[view]/[date]/+page.svelte:344`. The VM also retained detached Mail views, tracked separately in #1375. VM snapshots and traces remain in ignored `artifacts/tabstorm-1338/` as `cpu4-after-storm-{1,3}.heapsnapshot` and `native-after-storm-{1,3}.heapsnapshot`; the trace files are `cpu4-budget-failure-trace.json` and `native-budget-failure-trace.json`. They are not committed.
Author
Owner

Correction to my previous comment: I re-counted the native #calendar-panel nodes. In both VM conditions the detached count was 0 after storm 1 and 1 after storm 3 (one named panel total at storm 1, two at storm 3). I incorrectly said one detached panel after both storms. The VM shows a smaller 0→1 increase than the local 2→10 result; the local retainer path remains the same.

Correction to my previous comment: I re-counted the native `#calendar-panel` nodes. In both VM conditions the detached count was 0 after storm 1 and 1 after storm 3 (one named panel total at storm 1, two at storm 3). I incorrectly said one detached panel after both storms. The VM shows a smaller 0→1 increase than the local 2→10 result; the local retainer path remains the same.
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal-v0#1356
No description provided.