Skip to content

test(fetch): widen fetch-leak RSS thresholds for macOS/Windows arm64 - #33988

Open
robobun wants to merge 2 commits into
mainfrom
farm/c5d06615/fetch-leak-thresholds
Open

test(fetch): widen fetch-leak RSS thresholds for macOS/Windows arm64#33988
robobun wants to merge 2 commits into
mainfrom
farm/c5d06615/fetch-leak-thresholds

Conversation

@robobun

@robobun robobun commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

test/js/web/fetch/fetch-leak.test.ts went red on :darwin: 14 aarch64 in build 71937 with three RSS-threshold failures:

error: fetch({compress}) leaked 35 MB over 80 rounds
error: fragmented compressed fetch leaked 43 MB over 60 rounds
error: expect(received).toBeGreaterThanOrEqual(expected)  Expected: = 43.359375  Received: 43.078125

Scanning Buildkite annotations for builds 68000-71940 shows this file has been flaking in dozens of PR runs for weeks:

  • the two compress tests (added in fetch: add automatic request body compression via compress option #32416) flake on the macOS 14 arm64 Tart runners with observed deltaMB of 25-43 against a 32 MB threshold (builds 69943, 69985, 70001, 70065, 70076, 70150, 70300, 71200, 71766, 71774, 71776, 71937)
  • should not leak using readable stream (fixture-6, threshold set in Fix effectively every native-code memory leak in Bun #30875) flakes on Windows 11 arm64 and Windows 2019 x64 with growth of 6-14 MB against a 5 MB threshold (builds 68050, 69125, 69225, 69675, 69735, 69755, 69840, 69885, 69901, 69918, 69925, 69941, 70068, 70085, 70096, 70108, 70114, 70160, 70200, 70800, 71712, 71725, 71731, 71778, 71782, 71792, 71794, 71904, 71937)

These are not leaks. Running the identical compress workloads five times on Linux x64 settles at 2-4 MB and 9-10 MB; the macOS Tart VMs (16 KiB pages, three co-tenant Buildkite agents on one M2 Ultra host) settle at 25-43 MB for the same allocation pattern, and Windows does not return allocator pages to the OS as aggressively between the iteration-250 sample and the final GC. A real per-request leak of the body/compressor state would produce hundreds of MB for the compress tests (80 rounds x 5 encodings x ~700 KiB) and >32 MB for fixture-6 (250 iterations x 128 KiB), as the existing comments already note.

Fix

Raise the non-ASAN thresholds:

  • compress-option and fragmented-decompressor tests: 32 -> 64 MB (matches the existing file:// response-url leak test in the same file; ~50% headroom over the worst observed 43 MB, still ~4x below a real leak)
  • fixture-6 MAX_MEMORY_INCREASE: 5 -> 20 MB (~40% headroom over the worst observed 14 MB, still below the 32 MB a body leak would produce)

ASAN thresholds are unchanged.

How did you verify your code works?

USE_SYSTEM_BUN=1 bun test test/js/web/fetch/fetch-leak.test.ts passes all 24 tests locally. Linux deltaMB values (2-4, 8-10, <5) are unchanged by this PR, so Linux would still catch a real leak well below the new thresholds.


no test proof · iteration 1 · Platform-specific test-only change; deferring to CI.

The two compress-option leak tests and the readable-stream fixture have
been flaking on the macOS 14 arm64 Tart runners and Windows 11 arm64
since they were introduced; build 71937 went red on darwin with all
three failing together.

On Linux x64 the same workloads settle at 2-4 MB / 9 MB / <5 MB, but on
the macOS Tart VMs (16 KiB pages, multiple co-tenant agents on one host)
the compress tests settle at 25-43 MB, and on Windows arm64 the
readable-stream fixture grows 6-14 MB between iteration 250 and the
final GC. None of these are leaks: a real per-request leak would show
hundreds of MB for the compress tests and >32 MB for fixture-6, as the
comments already state.

Raise the non-ASAN thresholds from 32 to 64 MB (matching the existing
file:// leak test) and from 5 to 20 MB respectively, keeping >2x
headroom over the worst observed CI values while still catching a real
leak by a clear margin.
@robobun

robobun commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 12:05 PM PT - Jul 11th, 2026

@robobun, your commit 506da3e has 3 failures in Build #71949 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 33988

That installs a local version of the PR into your bun-33988 executable, so you can run:

bun-33988 --bun

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

Fetch leak threshold updates

Layer / File(s) Summary
Update fetch leak test thresholds
test/js/web/fetch/fetch-leak.test.ts
Non-ASAN memory thresholds are increased for compressed-response and readable-stream leak tests, with comments documenting observed runner measurements and allocator retention.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: widening fetch leak RSS thresholds for macOS/Windows arm64.
Description check ✅ Passed The description includes both required sections and gives the change rationale plus verification details.

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

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — test-only RSS threshold widening backed by CI flake history; new thresholds still well below what a real per-request leak would produce.

What was reviewed:

  • Verified fixture-6 runs 250 iterations between sample and final GC — 250 × 128 KiB = 32 MiB for a real body leak, so the new 20 MiB threshold still catches it.
  • Checked the compress-test math: 80 rounds × 5 encodings × ~700 KiB ≈ 280 MB for a per-request leak, ~4× above the new 64 MB threshold.
  • Confirmed ASAN thresholds are unchanged and no test logic was altered — only three numeric constants plus explanatory comments.
Extended reasoning...

Overview

This PR touches a single test file, test/js/web/fetch/fetch-leak.test.ts, changing three numeric RSS-delta thresholds (32→64 MB in two compress tests, 5→20 MB in the fixture-6 readable-stream test) and adding inline comments explaining the platform-specific allocator behavior that motivates the change. No runtime code is touched; ASAN thresholds are left as-is.

Security risks

None. This is a test-only change to memory-leak assertion thresholds. No user-facing code, no input handling, no auth/crypto/permissions.

Level of scrutiny

Low-to-medium. The change is mechanical (three integer constants), but leak-test thresholds are a safety net, so the key question is whether the widening still catches the property the tests protect. I verified:

  • Compress tests: 80 rounds × 5 encodings × ~700 KiB bodies would leak ~280 MB if the compressor state or body Vec were retained per-request. 64 MB is ~4× below that, and matches the threshold already used by the file:// leak test in the same file.
  • Fixture-6: I read fetch-leak-test-fixture-6.js — it samples RSS at iteration 250 and compares against iteration 500 + a final Bun.gc(true). 250 iterations × 128 KiB body = 32 MiB for a real body leak; the new 20 MiB threshold still trips on that with margin.
  • The PR description cites ~40 Buildkite builds where these tests flaked with observed deltas of 25–43 MB (macOS arm64 Tart) and 6–14 MB (Windows), which is consistent with allocator page retention rather than a monotonically growing leak.

Other factors

  • The repo's own guidance says "RSS thresholds need ~2x headroom" and "when de-flaking, keep asserting the property the original assertion protected" — this change satisfies the latter (the assertion still catches a real per-request leak by a wide margin) and gets close to the former (~1.5× over worst observed).
  • ASAN lanes retain their tighter behavior, so a real leak would still be caught there independently.
  • No prior reviews or outstanding comments on this PR; the bug-hunting system found nothing.
  • The added comments are concise and explain why the thresholds differ per-platform, which is exactly what the file's existing comments do for the ASAN branches.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — test-only threshold widening for known-flaky RSS leak tests, well-documented with CI evidence.

What was reviewed:

  • Confirmed the three changed values are non-ASAN RSS thresholds only; ASAN thresholds and test logic unchanged.
  • Verified fixture-6 reads MAX_MEMORY_INCREASE as an integer MiB bound at fetch-leak-test-fixture-6.js:23, so "20" behaves as intended.
  • Checked the leak-detection property is preserved: real per-request leaks would produce hundreds of MB (compress tests) / >32 MB (fixture-6), well above the new 64/20 MB thresholds.
  • Considered per-platform branching vs global widening — Linux baselines (2-10 MB) sit far below either threshold, so no meaningful precision is lost.
Extended reasoning...

Overview

This PR touches a single test file, test/js/web/fetch/fetch-leak.test.ts, and changes three numeric constants:

  • Two deltaMB > 32deltaMB > 64 in the compress-option and fragmented-decompressor RSS leak tests
  • MAX_MEMORY_INCREASE: "5""20" for the fixture-6 readable-stream leak test

Each change is accompanied by an inline comment documenting the observed platform-specific RSS behavior (macOS arm64 Tart runners settling at 25-43 MB, Windows/macOS arm64 at 6-14 MB) and the headroom remaining before a real leak would be missed. No test logic, no production code, and no ASAN thresholds are modified.

Security risks

None. This is a test-only change to memory-growth threshold constants. No user-facing code, no input handling, no auth/crypto/permissions.

Level of scrutiny

Low. The change is mechanical (three integer literals plus comments), self-contained to one test file, and backed by an extensive PR description citing ~40 specific Buildkite build numbers where these thresholds flaked. The rationale is sound: RSS-based leak detection is inherently allocator- and platform-sensitive, and the new thresholds retain the property the tests protect — a real per-request body/compressor leak would grow RSS by hundreds of MB (80×5×700 KiB) or >32 MB (250×128 KiB), which the 64 MB and 20 MB thresholds still catch with ~4× and ~1.6× margin respectively.

I cross-checked fetch-leak-test-fixture-6.js to confirm MAX_MEMORY_INCREASE is parsed via parseInt and used as a MiB delta bound in expect(rssSample).toBeGreaterThanOrEqual(memoryUsage - maxMemoryIncrease), so the string "20" is correct.

Other factors

The repo's own guidance suggests "branch per-platform rather than dropping precision" when de-flaking. I considered whether this PR should have gated the higher thresholds on isMacOS/isWindows. However, Linux measurements cited in the PR (2-4 MB, ~9 MB, <5 MB) are so far below even the old thresholds that raising the global threshold does not meaningfully reduce Linux sensitivity — a Linux regression from 4 MB to 60 MB would still be a very obvious leak signal. The added comments explicitly document the platform-specific numbers, which is the important part for future maintainers. Given the simplicity and the clear evidence trail, this doesn't warrant blocking.

No prior reviewer comments to address, no bugs found by the bug-hunting system, and no CODEOWNERS on this test file.

@robobun

robobun commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

CI status: build 71949 is complete. fetch-leak.test.ts passed on every lane including :darwin: 26 aarch64 (24 pass / 0 fail, compress deltaMB 7 and 9) and all 8 :windows: 11 aarch64 shards, with no fetch-leak entry in any failure or flaky annotation.

The three reds are all pre-existing main breaks unrelated to this test-only diff, each already being handled separately:

Build 71947 before it failed only on Tart-VM SSH auth during checkout rsync (the test suite never ran). This diff is ready to merge with those unrelated failures set aside.

robobun added a commit that referenced this pull request Aug 8, 2026
…l, widen the stream allowance to 20 MiB

The 16 KiB bodies shrank the guarded HiveRef leak signature to 256 MiB,
which the 320 MiB ASAN bound sat above, so the ASAN lane could no longer
fail on the regression it guards. Cap the child's quarantine like the
readable-stream test already does and bound at 128 MiB: clean ASAN runs
measure deltaMB 5-7, a simulated retained-body leak measures +278.

Windows lanes measured up to 14 MiB of non-leak RSS drift over the
fixture-6 sample window (scan in #33988), leaving the 16 MiB allowance
only 2 MiB of headroom; move it to 20 MiB, still well under the 32 MiB
the guarded regression produces.
@robobun

robobun commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator Author

Heads up: #37209 now carries the fixture-6 allowance change, sized at 20 MiB using the Windows measurements from this PR. The readable-stream hunk here will conflict once that merges and can be dropped; the two compress-test hunks are untouched by #37209 and remain this PR's scope.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant