Skip to content

feat(scripts): Bun.gc relief evaluation harness (SIGUSR2 GC channel, matched arms) - #2303

Open
lidge-jun wants to merge 2 commits into
codex/bun14-mem-diagnosticsfrom
codex/bun14-gc-relief-eval
Open

feat(scripts): Bun.gc relief evaluation harness (SIGUSR2 GC channel, matched arms)#2303
lidge-jun wants to merge 2 commits into
codex/bun14-mem-diagnosticsfrom
codex/bun14-gc-relief-eval

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

  • Phase A of the GC-relief plan (devlog/_plan/260822_260822-bun14-followup-memory/020): a measurement harness to evaluate the 260731 allocator-residual gate on Bun 1.4 — no production GC call is added by this PR.
  • scripts/macos-rss-retention-harness-child.ts gains a SIGUSR2 handler that runs Bun.gc(true) inside the measured proxy and reports a timestamped {type:"gc",at,durationMs} receipt on the existing stdout JSONL channel. Inert for the locked 7h retention protocol (it never sends SIGUSR2).
  • NEW scripts/bun-gc-relief-eval.ts: matched control/gc arms with two SEPARATE cell types — rss cells stay idle through +5s/+60s samples (criterion-a evidence uncontaminated), latency cells run an identical post-intervention probe stream whose p99 is the criterion-c oracle. Reuses the real startServer child + a Responses-shaped SSE fixture.
  • Bun 1.4 quirk documented in-code: Bun.spawn handle.kill() does not deliver SIGUSR2; process.kill(pid) is used deliberately.
  • Stacked on feat(memory): expose JSC extraMemorySize in system memory API, watchdog, and doctor #2302 (needs extraMemorySize diagnostics); parent docs PR devlog: Bun 1.4 follow-up memory roadmap (research + decade docs) #2301. Design was adversarially audited across 5 review rounds before implementation.

Verification

  • OCX_GC_EVAL_SMOKE=1 bun scripts/bun-gc-relief-eval.ts — exit 0; GC receipts flow (durationMs ~4.5ms), 4 cells + report.json written; smoke artifacts are labeled smoke:true and are not comparison evidence.
  • bun x tsc --noEmit — exit 0.
  • Real 3-run gate evidence lands with the macmini-cf measurement pass (roadmap 040).

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

…nnel + matched-arm cells)

Phase A of the GC-relief plan: evaluate the 260731 allocator-residual gate on
Bun 1.4 before any production hook. The retention-harness child gains a
SIGUSR2 handler that runs Bun.gc(true) in the measured process and reports a
timestamped {type:"gc",durationMs} receipt (inert for the locked 7h protocol,
which never sends SIGUSR2). bun-gc-relief-eval.ts orchestrates matched
control/gc arms with SEPARATE rss-retention and latency cell types so the RSS
criterion is never contaminated by probe traffic; latency cells use a
post-intervention probe stream as the p99 oracle.

Note: Bun.spawn handle.kill() does not deliver SIGUSR2 on Bun 1.4 —
process.kill(pid) is used deliberately.

Smoke-verified end to end (OCX_GC_EVAL_SMOKE=1): GC receipts flow, report.json
written. Real 3-run evidence lands with the macmini-cf measurement pass.

Unit: devlog/_plan/260822_260822-bun14-followup-memory/020
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 21, 2026 15:48
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • ^dev$
  • ^preview$

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 04e08817-12e5-488a-8f7c-cf4f54502842

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Reviewed exact head 28e8232edaab14c64fc080527f255e4fe063fd63 against the stacked base and the controlling 260731/020/040 measurement contracts.

The production boundary is good: this PR does not add a runtime GC hook. I am requesting changes because the harness cannot yet produce the evidence it says it produces.

  1. runCell records rssAfterLoad, rssPlus5s, and rssPlus60s, but no pre-load RSS. The controlling gate is “at least 50% of post-load RSS growth is gone,” which requires a baseline and a normalized recovery fraction. rssAfterLoad - rssPlus60s alone cannot distinguish recovery from ordinary baseline drift. The plan also says the 1.4 evaluation reads extraMemorySize and reports the counter changes, but this harness never calls /api/system/memory; the #2302 dependency is therefore unused. Capture baseline/after-load/+5s/+60s memory snapshots, including the optional extra-memory counter, and calculate the criterion from the baseline-relative growth.

  2. The measurement protocol requires identical concurrent request streams for the tail-latency control. oneTurn is awaited in a plain for loop for both load and probes, so this is a serial single-request workload. It cannot establish the documented concurrent p99 criterion. Use a bounded, identical concurrency schedule in both arms and report its parameters. Also counterbalance arm order (or otherwise remove the fixed control-then-GC ordering) so host drift is not confounded with the intervention.

Please add focused harness tests for the report math and scheduling contract, then rerun the smoke probe and exact-head CI. The parent #2302 blockers still need to be resolved independently before this stacked PR can land.

…s, Phase B not implemented

Real 3-run matched-arm evaluation on two darwin/arm64 hosts (local + macmini-cf,
both Bun 1.4.0): recoveredByPlus60s in the GC arm is indistinguishable from
control idle drift (<0.1% of the ~300MB post-load RSS; less than control on 4/6
runs). Criterion (a) of the 260731 allocator-residual gate fails decisively;
GC pause 3.9-4.6ms recorded. Production Bun.gc(true) relief stays banned; the
Phase B design is retained as documentation for a future runtime that changes
page-return behavior. Evidence JSONs committed under evidence/.
@lidge-jun

Copy link
Copy Markdown
Owner Author

Phase A real-run verdict is in: FAIL — the 260731 gate stands on Bun 1.4.

3 fresh-process runs per arm on two darwin/arm64 hosts (local + macmini-cf), both Bun 1.4.0. recoveredByPlus60s in the GC arm is indistinguishable from control idle drift (<0.1% of the ~300MB post-load RSS; GC arm recovered less than control on 4/6 runs). GC pause 3.9–4.6ms. Criterion (a) fails decisively, so no latency acceptance was computed.

Consequence: no production Bun.gc(true) hook lands (Phase B stays documentation-only). Evidence committed in devlog/_plan/260822_260822-bun14-followup-memory/evidence/ (commit 3ee558a). The harness itself remains the deliverable of this PR — it is the re-evaluation tool for any future Bun runtime that changes allocator page-return behavior.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Re-reviewed exact head 3ee558a23877f43ebd6e7532c57af61e353b283c. The added two-host runs are useful directional evidence and support keeping Phase B disabled, but they do not resolve the measurement-contract blockers on the harness. I am keeping CHANGES_REQUESTED.

  1. The committed RSS records still begin at rssAfterLoad; there is no pre-load baseline and no baseline-relative recovery fraction. The new verdict divides the recovered bytes by the entire post-load RSS (“<0.1% of load-height RSS”), which is not the controlling criterion: at least 50% of post-load RSS growth must be gone. The data may well lead to the same FAIL conclusion, but this report cannot prove that gate without rssBeforeLoad, postLoadGrowth, and recoveryFraction.

  2. The latency cells are still serial: for (...) await oneTurn(...). The document now calls the p99 values informational, which is appropriate after criterion (a) fails, but the PR also states that the harness is the reusable deliverable for a future Bun runtime. In its current form it still cannot run the documented identical concurrent tail-latency control, and fixed control→GC arm order remains confounded with host drift. Either implement the bounded concurrent/counterbalanced schedule and focused report-math tests, or narrow the PR/documentation claim so this artifact is explicitly only the current serial exploratory run and is not presented as the future acceptance harness.

  3. The verdict heading is dated 2026-08-22, but the evidence and current review date are 2026-08-21. Correct the future date. The committed reports should also carry enough provenance to reproduce/compare them (at minimum the harness/source commit and host identity label); the current JSON has neither a schema/version nor a host field.

The safe production decision remains clear: do not land a Bun.gc(true) runtime hook from these results. Exact-head CI is otherwise largely green, with macOS still running, but CI cannot repair the missing measurement fields and scheduling contract. The stacked parent #2302 remains independently blocked.

@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 46 / 80

지금 dev HEAD c0cbe494e에 프로덕션 Bun.gc 훅 없음. src/server/memory-watchdog.ts:79-90 defaultSampleprocess.memoryUsage()만. extraMemorySize도 아직 없음. 그건 #2302. 이 PR base가 dev가 아님. codex/bun14-mem-diagnostics (#2302). 파일 5개. gh api pulls/2303/files: scripts/bun-gc-relief-eval.ts +294, scripts/macos-rss-retention-harness-child.ts +22, devlog/_plan/260822_260822-bun14-followup-memory/020_watchdog_gc_relief.md +38, evidence JSON 둘. 드래프트 아님. 런타임 핫패스 아님. 측정 하네스 + 게이트 FAIL 기록임.

핵심. 차일드 macos-rss-retention-harness-child.ts가 SIGUSR2에서 Bun.gc(true) 돌리고 stdout JSONL에 type:"gc" receipt. 락된 7h 리텐션은 SIGUSR2를 안 보냄. 오케스트레이터 scripts/bun-gc-relief-eval.ts가 rss 셀이랑 latency 셀을 갈라둠. rss는 로드 후 개입 다음 +5s/+60s를 아이들. latency는 개입 다음 프로브 스트림 p99. 컨트롤은 50ms 슬립. GC 암은 process.kill(pid, SIGUSR2). 주석이 맞음. Bun 1.4 handle.kill()이 SIGUSR2를 안 줌. 픽스처는 Responses SSE. response.output_text.delta × 200 × 65_536B. startServer 실자식. 스모크 OCX_GC_EVAL_SMOKE=1은 셀을 줄이고 smoke:true. 비교 증거 아님.

이미 실측이 들어옴. 3ee558a. 로컬+macmini-cf, Bun 1.4.0 darwin/arm64, smoke:false. criterion (a) FAIL. load 후 RSS ~300–350MB. recoveredByPlus60s가 컨트롤 아이들 드리프트랑 같음. GC 암이 컨트롤보다 덜 회수한 런이 6중 4. pause 3.9–4.6ms. Phase B 안 넣음. 260731 게이트 유지. 그 결론은 맞음. 프로덕션 워치독에 gcRelief 넣지 말 것. 이 PR 범위가 그거임.

구멍. (1) 차일드가 type:"gc-error"를 쓰는데 오케스트레이터 gcWaitertype:"gc"만 받음. 에러면 10초 타임아웃. receipt 유실. (2) waiter가 슬롯 하나. SIGUSR2 두 번이면 둘째는 버림. (3) rss()ps -o rss= × 1024. darwin/linux ps rss는 KiB라 맞음. 다른 컬럼이랑 섞지 말 것. (4) SIGUSR2를 7h 부모/슈퍼바이저가 보내면 리텐션 RSS가 오염됨. 주석만 가드임. 핸들러를 평가 전용 플래그로 가리거나 평가 차일드를 분리하는 게 더 안전. (5) src/tests 0. tsc만. (6) #2302 없이 dev에 리베이스하면 extraMemorySize 커밋이 빠짐. 이 하네스는 extraMemorySize를 안 읽음. 동작은 됨. 스택을 뒤집지 말 것.

types.ts/config.ts 안 만짐. 스플릿 안 씹힘. 리베이스하지 말고 닫으라는 케이스 아님. 닫을 중복 아님. #2188 L1–L9 사이드카 이미 dev. x_search 넣지 말 것. Grok OAuth Chat 기본(#2255)/GUI 옵트인 Responses(#2266)/#2283이랑 다른 레인임. 프리뷰 배포 아님. #2292/#2293 윈도우 피커랑 안 겹침. 카탈로그는 그대로 Ox Alpha x-preview-f-free + deepseek-v4-flash-vision-exp. v2.29.0 태그됨. v2.30.0-preview.20260821 있음. 측정 FAIL 기록이 가치임. 핫패스 아님. 그래서 46. #2301#2302 다음.

해결방안: #2301/#2302 먼저. 그 다음 이 패치. Phase B/gcRelief 이 PR에 넣지 말 것. 플랜 문구대로. gc-error를 waiter가 reject하게 해라. 7h 차일드 SIGUSR2는 env 가드. OCX_GC_EVAL=1일 때만 핸들러. 스모크 아티팩트를 게이트 증거로 쓰지 말 것. 이미 라벨 있음. 유지. 스플릿이 memory-watchdog.ts/scripts 하네스를 옮기면 리베이스하지 말고 닫고 다시 짜라. 지금은 그 정도 아님.

이 댓글은 grok-bot이 작성했습니다

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants