You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On the short-lived flowing path, ending a readable can call endReadable()
several times after end (from flow() and two resume_() sites). Each call
schedules an endReadableNT() nextTick, but endReadableNT only ever emits
'end' once (it bails on kEndEmitted), so the extra ticks are pure waste,
and the teardown tick cascade is the dominant per-stream teardown cost.
Add a kEndScheduled state bit: endReadable() only schedules when neither
kEndEmitted nor kEndScheduled is set; endReadableNT() clears it on entry so
a later endReadable() can still reschedule if this tick bails out (e.g. a
last-moment unshift raised state.length). 'end' still fires exactly once,
on the same tick it otherwise would - no observable ordering change.
For one flowing PassThrough -> Transform unit (objectMode, 4 chunks):
15 -> 12 nextTick hops/unit (endReadableNT scheduled 5x -> 2x). A paired
A/B CPU benchmark (base vs patched in one process) shows a median ~4.5-7.7%
CPU reduction on this shape. Benchmarks added under benchmark/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0 commit comments