dillon1000/react
Commit
Browse files [Fixture] flight-ssr-bench: drain immediates between iterations to fix false memory leak (#36968)
Claude found this while running the Flight/Fizz bench. --- While measuring memory in this fixture, the Flight server appeared to leak ~140KB per render: `heapUsed` grew steadily across hundreds of renders even with forced GC, and roughly 3x worse when a Flight client consumed the stream in the same process. Fizz-only runs were flat, so it looked like a real Flight leak. On a closer look, the benchmark loop seems to be lying. React schedules one `setImmediate` per request, but every render in this fixture completes entirely in promises and `nextTick` callbacks, so a tight benchmark loop never gives the event loop a chance to run immediates at all. They quietly pile up, and each pending callback keeps its already-finished request alive. Heap snapshots show that every "leaked" request was held by a pending immediate, and nothing else. Adding a single `await setImmediate` per iteration makes memory completely flat over 300 renders, with or without a same-process Flight client. A real server yields to the event loop on every request, so this can't happen outside a synthetic loop. The fix is to yield to the event loop between benchmark iterations, outside the timed window, so latency numbers are unaffected. Each variant now also reports how much heap it retains after the run settles. That number was meaningless before — the pile-up made variants with bigger per-request graphs look like they used more memory when they didn't. After the fix, a full `yarn bench:bare` run retains +0.3–0.6MB total per variant after 1000 iterations (JIT/warmup noise), instead of drifting by hundreds of MB. --------- Co-authored-by: Claude Fable 5 <[email protected]>
Changed paths2 files
First-parent comparisonfixtures/flight-ssr-bench/README.md ModifiedM fixtures/flight-ssr-bench/bench.js ModifiedPatch
Files changed
Rendering syntax-highlighted changes…