Skip to content

perf(server): replace quadratic task queue drain with index-based FIFO - #37464

Open
mturac wants to merge 1 commit into
react:mainfrom
mturac:fix/issue-37453
Open

perf(server): replace quadratic task queue drain with index-based FIFO#37464
mturac wants to merge 1 commit into
react:mainfrom
mturac:fix/issue-37453

Conversation

@mturac

@mturac mturac commented Aug 30, 2026

Copy link
Copy Markdown

Summary

Fixes #37453 — the browser server stream scheduler stores pending callbacks in an array and removes one per MessageChannel delivery with Array.shift(). Each shift copies every remaining element, making queue draining O(n²) in the number of scheduled tasks during a burst.

Fix: Replace shift() with a head-index that advances in O(1). Consumed slots are nulled out so callbacks can be garbage-collected. When the consumed prefix exceeds both 1024 entries and half the array length, the live tail is compacted into a fresh array. This preserves FIFO ordering, supports reentrant scheduling, and keeps amortized memory bounded.

Changed files

  • packages/react-server/src/ReactServerStreamConfigBrowser.js — replace shift() with indexed dequeue and periodic compaction

Test plan

  • ReactDOMFizzServer-test.js — 183/183 passed (core SSR streaming tests)
  • packages/react-server/ — 2/3 suites passed (1 pre-existing snapshot failure in ReactFlightAsyncDebugInfo-test.js, unrelated to this change — confirmed by running on unmodified main)
The browser server stream scheduler used Array.shift() to dequeue
callbacks one at a time.  shift() moves every remaining element on each
call, making a burst of n scheduled tasks O(n²) to drain.

Replace with a head-index that advances in O(1).  Null out consumed
slots so the callbacks can be collected, and compact the underlying
array when the consumed prefix exceeds both 1024 entries and half the
array length, keeping amortized memory bounded.

Fixes react#37453
@meta-cla meta-cla Bot added the CLA Signed label Aug 30, 2026
@github-actions

Copy link
Copy Markdown

A size report will appear here when the build finishes.

Generated by sizebot against acd4d5c

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

1 participant