The same CPU work, run three ways. The blue dot is driven by
requestAnimationFrame, so it only moves when the browser gets a
turn โ if it stops, your thread is blocked. Run each mode and
watch the dot, then try clicking the button mid-run.
Workload is calibrated to real CPU time on your machine, so 600 ms means
roughly 600 ms of actual arithmetic. The yield budget only affects the two
yielding modes โ it is the > 50 in
if (performance.now() - lastYield > 50).
โLongest freezeโ is the biggest gap between two animation frames. Anything over ~50 ms is what Chrome DevTools flags as a long task; over ~200 ms and users assume your app is broken.
| mode | frames | longest freeze | clicks heard | total |
|---|
Run all three with the same workload. Blocking is the one that should look obviously
broken: a single frame and one enormous freeze. Both yielding modes keep the worst
freeze near your budget instead. Between those two, expect
scheduler.yield() to finish sooner โ browsers clamp nested
setTimeout to roughly 4 ms per hop, and across hundreds of hops that
adds up, while a yield continuation resumes in a boosted task queue.
setTimeout(0) may well paint more frames along the way; it is buying them
with wall-clock time you did not choose to spend.
The highlighted line is the only difference between the modes.