From 27577699d5f87d65d886881601a4d663b8b78ca0 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Tue, 11 Aug 2026 18:24:01 +0000 Subject: [PATCH] test: warm up the import() file-path leak fixture and shorten its loop esm-fixture-leak-small.mjs ran 100k import() loads to get a leak signal that cleared the 5-10 MB of heap growth a 5-load warmup left inside the measurement. On the 4 vCPU Linux CI agents that loop takes 20-27s of the test's 30s budget while it shares the machine with the other fixtures in require-cache.test.ts, and on a slow agent it timed out on all four attempts. Warm up for 2k loads so the baseline is taken at steady state, then measure 40k loads against a 20 MB bound. A non-leaking build measures 0-7 MB (Linux x64, 20 runs; Windows x64, 10 runs), the 1 KB per load leak this fixture exists for measures 40 MB or more, and the fixture takes about a third of the time. --- test/cli/run/esm-fixture-leak-small.mjs | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/test/cli/run/esm-fixture-leak-small.mjs b/test/cli/run/esm-fixture-leak-small.mjs index 71fb83e6fa07..6f6540985b11 100644 --- a/test/cli/run/esm-fixture-leak-small.mjs +++ b/test/cli/run/esm-fixture-leak-small.mjs @@ -9,15 +9,23 @@ const rss = ? Bun.unsafe.memoryFootprint : process.memoryUsage.rss; +// The JS heap and allocator grow by 5-10 MB over the first couple thousand +// loads and then hold steady. Taking the baseline after that leaves only +// per-load growth inside the measured window, which is what lets the window be +// 40k loads instead of the 100k this fixture used to need (20-27s on the 4 vCPU +// CI agents, against the test's 30s budget). +const warmupLoads = 2_000; +const measuredLoads = 40_000; + if (typeof Bun !== "undefined") Bun.gc(true); -for (let i = 0; i < 5; i++) { +for (let i = 0; i < warmupLoads; i++) { delete require.cache[dest]; await import(dest); } if (typeof Bun !== "undefined") Bun.gc(true); const baseline = rss(); -for (let i = 0; i < 100000; i++) { +for (let i = 0; i < measuredLoads; i++) { delete require.cache[dest]; await import(dest); } @@ -27,19 +35,10 @@ setTimeout(() => { let diff = rss() - baseline; diff = (diff / 1024 / 1024) | 0; console.log({ leaked: diff + " MB" }); - // This test seems to be more flaky on slow filesystems. - // This used to be 40 MB, but the original version of Bun which this triggered on would reach 120 MB - // so we can increase it to 100 and still catch the leak. - // - // ❯ bunx bun@1.0.0 --smol test/cli/run/esm-fixture-leak-small.mjs - // { - // leaked: "100 MB" - // } - // ❯ bunx bun@1.1.0 --smol test/cli/run/esm-fixture-leak-small.mjs - // { - // leaked: "38 MB", - // } - if (diff >= (isASAN ? 500 : 100)) { + // The leak this guards against retained about 1 KB per load (bun 1.0.0 + // measured 100-120 MB over 100k loads), so 40k loads of it are 40 MB or more. + // A non-leaking release build measures 0-7 MB here (20 runs, Linux x64). + if (diff >= (isASAN ? 500 : 20)) { console.log("\n--fail--\n"); process.exit(1); } else {