Skip to content

test: bound the footprint check by reads on both sides of the capture - #16141

Merged
austinywang merged 1 commit into
mainfrom
15488-footprint-bracket
Sep 30, 2026
Merged

austinywang merged 1 commit into
mainfrom
15488-footprint-bracket

Conversation

@austinywang

@austinywang austinywang commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

CmuxTopSnapshotScopeTests.testSummaryPayloadIncludesPhysicalFootprintMemoryBytes compared the snapshot's memory_bytes with a footprint read taken before the capture. The capture reads the footprint later, and the app host's footprint moves in between. In the #15488 validation run (shard 3 of run 36749306412) the two reads were 112 MiB apart (exactly 7 × 16 MiB), past the 20% tolerance. Part of #15488.

Why the reads drift

Since #13014 the capture is an async request to the app's shared snapshot service. It runs off the main thread and can wait behind the host's own users of that service, while the host keeps allocating and freeing. Before #13014 the test was synchronous and the capture ran inline, so nothing ran between the two reads. The product is right:

  • capture() asks for a snapshot taken after the request, so it never reuses an older one.
  • memory_bytes comes from ri_phys_footprint, the same field the test reads.
  • The 112 MiB gap is a multiple of the 16 KiB page and sits 2,180 B past a page boundary, like the pre-read. The resident-size fallback is always page-aligned, so both values were footprint reads.

The test passed in 104 of 105 runs scanned in main and PR logs since 2026-09-20. This duration ranged from 0.026 s to 8.1 s.

Change

The test reads the footprint again after the capture. It requires memory_bytes to be within the same tolerance, max(16 MiB, 20%), of the range the two reads span. With no drift the accepted range is the same as before. It also requires memory_source_fallback_pids to be empty, which shows the value came from ri_phys_footprint. The helper's proc_pid_rusage call moves onto one line to keep the file within its length budget.

Evidence

Each run holds 256 MiB of dirty memory from just after the first footprint read, through the capture, on diag refs over main's 4df2a40 app products (run 36748094366), with app-host-test-rerun.yml, 5 iterations each. The second pair leaks the buffer so every iteration dirties fresh pages:

current test this change
buffer leaked each iteration run 36762586974: failed 5 of 5, abs(memoryBytes - expectedFootprintBytes) 256–345 MiB over tolerance run 36762592170: passed 5 of 5
buffer freed each iteration run 36758205468: failed iteration 1 (268714176 against a 55017760 tolerance) run 36758211016: passed 5 of 5

In the freed pair, iterations 2–5 reallocate pages the footprint still counts, so only iteration 1 drifts.

This PR's own CI also ran the fixed test in its shard, with no injected drift, and it passed.

No local build or test run; this Mac does not compile cmux.

Changelog

none

🤖 Generated with Claude Code


Summary by cubic

Stops testSummaryPayloadIncludesPhysicalFootprintMemoryBytes from flaking when the app host's footprint moves between the test's reference read and the async capture.

  • Reads the footprint again after the capture and requires memory_bytes to fall within the same tolerance of the range the two reads span; with no drift the accepted range is unchanged.
  • Also asserts memory_source_fallback_pids is empty to prove the value came from ri_phys_footprint.
  • Moves the helper's proc_pid_rusage call onto one line to keep the file within its length budget.

Written for commit 3877b95. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Tests
    • Updated memory-footprint checks to compare reported usage with readings taken before and after snapshot capture, allowing for expected variation.
    • Added verification that the readings do not rely on a fallback memory source.

testSummaryPayloadIncludesPhysicalFootprintMemoryBytes compared the
snapshot's memory_bytes with a footprint read taken before the capture.
Since #13014 the capture is an async request to the app's shared
snapshot service, which may wait behind the host's own census users
while the host keeps allocating and freeing. The capture's own
footprint read therefore lands some time after that reference. In
#15488's validation run the host footprint moved 112 MiB (7 x 16 MiB)
in that gap, past the 20% tolerance.

The test now reads the footprint again after the capture and requires
memory_bytes to be within the same tolerance of the range the two reads
span. With no drift the accepted range is unchanged. It also requires
memory_source_fallback_pids to be empty, which shows the value came from
ri_phys_footprint rather than the resident-size fallback.

Refs #15488

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 95070a66-2c3a-479d-aa04-80601bfed272

📥 Commits

Reviewing files that changed from the base of the PR and between e6662a5 and 3877b95.

📒 Files selected for processing (1)
  • cmuxTests/CmuxTopSnapshotScopeTests.swift

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The physical-footprint summary test now brackets snapshot capture with two readings, checks the snapshot value against that range with a size-based tolerance, and asserts that no PIDs used a memory-source fallback.

Changes

Snapshot Memory Validation

Layer / File(s) Summary
Bracketed physical-footprint assertion
cmuxTests/CmuxTopSnapshotScopeTests.swift
The test compares the snapshot value with physical-footprint readings taken before and after capture, using a tolerance of the greater of 16 MiB or 20%. It also checks that no PIDs used a memory-source fallback. The proc_pid_rusage call was reformatted without changing its arguments or result handling.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~5 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to 3877b

This is a bounded test-only change, and source inspection found no merge-blocking issue. The test has not been run locally, so normal CI validation remains useful.

🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 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.
Cmux Cloud Persistent Session And Early Input ✅ Passed PASS: The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The diff adjusts footprint assertions around an asynchronous snapshot capture and reformats proc_pid_rusage; it does not change…
Cmux Swift Actor Isolation ✅ Passed PASS: The authoritative diff changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The changes are limited to test assertions, footprint reads, and formatting of an existing test helper call. No p…
Cmux Swift Blocking Runtime ✅ Passed PASS: The only changed file is cmuxTests/CmuxTopSnapshotScopeTests.swift, a test target. The diff adds footprint reads, range calculations, and an assertion around an existing asynchronous capture. …
Cmux Browser Automation Off-Main ✅ Passed PASS: The pull request changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The diff updates footprint assertions and reformats proc_pid_rusage; it does not modify browser socket commands, `Ter…
Cmux Expensive Synchronous Load ✅ Passed PASS. The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The diff adjusts physical-footprint test reads and reformats proc_pid_rusage; it adds no production Swift code and no agent-his…
Cmux Cache Substitution Correctness ✅ Passed PASS: The pull request changes only cmuxTests/CmuxTopSnapshotScopeTests.swift, not production Swift, TypeScript, or JavaScript. The diff adds a second physicalFootprintBytes read and bounds the te…
Cmux No Hacky Sleeps ✅ Passed PASS. The pull request changes only cmuxTests/CmuxTopSnapshotScopeTests.swift, which is Swift test code. The diff adds footprint reads and assertions, plus reformats an existing proc_pid_rusage ca…
Cmux Algorithmic Complexity ✅ Passed PASS. The only changed file is cmuxTests/CmuxTopSnapshotScopeTests.swift, and the diff changes test assertions plus formatting in a test helper. The new operations inspect a single test payload and …
Cmux Swift Concurrency ✅ Passed The pull request changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The diff adds a second synchronous footprint read and adjusts assertions; it does not add DispatchQueue, DispatchGroup, C…
Cmux Swift @Concurrent ✅ Passed PASS. The diff changes only an unisolated test method and a synchronous proc_pid_rusage helper call. It adds no nonisolated async function, @concurrent annotation, actor-isolated access, or UI-i…
Cmux Swift Package Boundaries ✅ Passed PASS: The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The diff updates test assertions and reformats a test helper call. It introduces no production Swift feature, reusable domain log…
Cmux Swiftpm Lockfiles ✅ Passed The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The diff contains no Package.swift, Package.resolved, Xcode project/workspace, .gitignore, workflow, or dependency-resolution cha…
Cmux Swift Logging ✅ Passed PASS. The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift, which is test code covered by the allowed test case. The diff adds no print, debugPrint, dump, NSLog, file/stdout diagnos…
Cmux User-Facing Error Privacy ✅ Passed PASS. The authoritative diff changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The changes are test assertions, test setup, and a developer-only comment. They do not add or change cmux user-fa…
Cmux Full Internationalization ✅ Passed PASS: The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The changes are test assertions, a developer-only comment, and formatting of a test helper call. They add no user-facing Swift te…
Cmux Swiftui State Layout ✅ Passed PASS. The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The diff updates footprint-test assertions and reformats a helper call. It adds no SwiftUI views, state wrappers, geometry measur…
Cmux Architecture Rethink ✅ Passed PASS. The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. It adds a second physicalFootprintBytes read around the asynchronous capture and tightens test assertions for the fallback list…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS. The PR changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. The additions adjust footprint assertions and reformat a helper call. They do not add or materially change NSWindow, NSPanel,…
Cmux Source Artifacts ✅ Passed The diff changes only cmuxTests/CmuxTopSnapshotScopeTests.swift, a tracked hand-written test source file. It adds test assertions and reformats an existing helper call. No local output, generated ar…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS: The authoritative diff changes only cmuxTests/CmuxTopSnapshotScopeTests.swift. It adds no Swift file under a production Sources/ path, so the production test/debug seam rule does not apply.
Title check ✅ Passed The title clearly and concisely describes the main change: bounding the footprint check using readings before and after capture.
Description check ✅ Passed The description explains the problem, implementation, testing evidence, and changelog status. It identifies that no local build or test was run and provides CI results. The omitted checklist and demo …
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@austinywang

Copy link
Copy Markdown
Contributor Author

Pre-merge review (correctness first, subagent): approve, no defects.

  • A correction, not a loosening. capture() requests a snapshot taken after the request (ProcessSnapshotService.swift:55), so its resource read happens between the two test reads. With no drift the accepted range is exactly the old one. With drift, the extra room equals the measured drift, and the 20% / 16 MiB tolerance is unchanged.
  • The fallback check is exact. For the test's own pid, proc_pid_rusage succeeds and the value is labeled footprint (CmuxTopProcessSampler.swift:104-114). Only the resident-size fallback adds a pid to memory_source_fallback_pids (CmuxTopSnapshot.swift:515).
  • Residual case: memory that spikes and is freed entirely between the two reads can still fail, as it could before.

Evidence update: the first red run (36758205468) failed iteration 1 as expected: abs(memoryBytes - expectedFootprintBytes) → 268714176 against a tolerance of 55017760. Iterations 2–5 passed because each reallocated the freed 256 MiB, which was still counted in the footprint, so there was no drift. A second pair leaks the buffer so every iteration dirties fresh pages: red 36762586974 and green 36762592170.

@austinywang
austinywang merged commit 96914e7 into main Sep 30, 2026
79 of 91 checks passed
@austinywang
austinywang deleted the 15488-footprint-bracket branch September 30, 2026 19:51
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