Skip to content

test(vm): measure retained memory after cache warmup - #131

Merged
steipete merged 3 commits into
mainfrom
claude/w179-vm-script-retention-guard
Oct 5, 2026
Merged

steipete merged 3 commits into
mainfrom
claude/w179-vm-script-retention-guard

Conversation

@steipete

@steipete steipete commented Oct 5, 2026 •

Copy link
Copy Markdown

The existing vm.Script leak test exceeds its 200 MiB cold RSS limit even when its wrappers and source providers are reclaimed. This change warms the allocator and code cache with 5,000 scripts, then measures the full 10,000-script workload. It collects between bounded batches and checks live Script cells. The 200 MiB release / 700 MiB ASAN limits and existing deadlines are unchanged. The measured 32 KiB sources total 312.5 MiB, so native source retention remains detectable.

Measuring all 10,000 scripts preserves the original per-script RSS budget. The final integration review identified that an earlier half-window proposal did not; the corrected full-workload guard has a scoped-clean P2 review.

Matched builds of Bun 0e6a7b354732a887a937f396db1283b8a1bd644e against three immutable WebKit releases produce overlapping distributions. On the fork's macos-15 shape, with its runner GC and integrity-audit settings:

WebKit Mean RSS delta Range Unchanged test
42ab38d705 (before coordinate cache) 203.01 MiB 201.16–203.78 MiB 0/12 pass
641c15f928 (coordinate cache) 202.97 MiB 202.36–203.44 MiB 0/12 pass
f1e1ca1156 202.92 MiB 201.88–203.61 MiB 0/12 pass

Across five separately reported local/CI configurations, all 180 unchanged test executions fail. Native provider instrumentation records zero coordinate lookups on the original workload’s vm.Script providers, approximately 98,000 providers destroyed per 100,000 scripts, and at most 2,000 retained providers. A separate stack-heavy workload exercises the coordinate cache and still tears down providers within that bound. This result does not call for a WebKit change.

The corrected guard passes 9/9 local runs across the three engines; observed growth is 154.47–155.38 MiB. It detects all 9/9 cases for each deliberate-retention control: wrappers reach 15,002 live Script cells; retained returned functions leave the Script count at two and grow RSS by 603.48–604.73 MiB; retaining a 25 KiB native buffer per script also leaves the Script count at two and grows RSS by 431.59–433.25 MiB. Control totals include the warmup. Native instrumentation independently confirms 15,000 providers created and zero destroyed for the function-retention control.

Three-engine CI qualification 37383373462 verifies all 15 guard/control gates. The real guard and observed normal case pass at their default timeout; deliberate-retention mutants use a diagnostic ceiling so they must reach the intended assertion. CI normal growth is 153.16–154.42 MiB; all three wrapper, function, and native-buffer controls are detected. These artifacts separately bind runtime source 0e6a7b354, embedded build revision 5c441bf48, each engine, each binary hash, and the corrected guard hash.

Exact product head 3e067ca205a7e7c130919133e700120e51bca6f4, based on main after #113, #132, and #130, passes the focused default-timeout guard, all seven VM files, both setup checks, and all three retention controls locally. Its tree stays clean and the runtime/engine identities are verified. P2 review is scoped-clean. Final native CI 37383859719 passes on its first attempt: Linux 16/16 and Darwin 12/12, including the VM guard at 2.54 seconds on Darwin. Its tested merge tree equals the reviewed product tree. Format and JavaScript lint pass.

Adapts the live-cell and batched-collection approach from the still-open oven-sh/bun#42474, while preserving this fork's RSS limits and full measured workload. The runtime and engine pin are unchanged.

The earlier 43b87ed44 head had the named Darwin watcher failure: run 37358157982, attempt 1, Darwin job 111925745591. At test/js/node/watch/fs.watch.rewrite.test.ts:94, expect(seen.some(p => p.startsWith("a/"))).toBe(false) expected false and received true after a recursive rename; runner cleanup subsequently raised ENOTEMPTY. The VM row and every other row passed. The cancelled old-head retry is not qualification evidence. No watcher assertion, skip, or deadline changed. Separate comparison reproduces the same delayed seed-event class on official upstream canary 13a98b0dbd (3/80 trials) and the fork (4/80), with matching watcher/test blobs; this is upstream-parity evidence, not a product fix or a trace of the original CI process.

Adapt the live-cell and batched-collection approach from oven-sh#42474 while preserving 10000 scripts in every profile and the original 200/700 MiB RSS bounds. Compare the second half against an identical warmup workload so allocator and code-cache startup do not masquerade as retained growth.
@steipete
steipete marked this pull request as ready for review October 5, 2026 19:41
@steipete
steipete marked this pull request as draft October 5, 2026 22:24
@steipete
steipete marked this pull request as ready for review October 5, 2026 22:58
@steipete
steipete merged commit 2518a31 into main Oct 5, 2026
6 checks passed
@steipete
steipete deleted the claude/w179-vm-script-retention-guard branch October 5, 2026 23:00
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.

1 participant