Skip to content

[Prototype] Node 24: count await continuations that block on their dispatch fiber (port of #12) - #13

Draft
jbaczuk-qualia wants to merge 1 commit into
jbaczuk/fiber-await-v24from
jbaczuk/fiber-await-v24-block-count
Draft

jbaczuk-qualia wants to merge 1 commit into
jbaczuk/fiber-await-v24from
jbaczuk/fiber-await-v24-block-count

Conversation

@jbaczuk-qualia

@jbaczuk-qualia jbaczuk-qualia commented Oct 7, 2026 •

Copy link
Copy Markdown

Summary

Stacked on #9 (the Node 24 port). Same change as the Node 18 version, #12. Adds Fiber.awaitContinuationBlocks, a process-wide count of code after an await that blocked on the hidden fiber the dispatcher gave it (Future.wait, Promise.await, a sync Meteor call). On stock fibers each of these throws "Can't wait without a fiber", so the count shows where code still depends on fibers after an await. Code that just runs on a dispatched fiber and never blocks behaves the same as on stock, so it isn't counted.

File Change
fibers_async.js Incremented in the dispatcher's existing "job blocked" branch (reuse dispatcher: run() !== kIdle and the fiber is still the dispatch fiber; one-off dispatch: the job didn't finish). Counted once per blocking job. Ordinary yields and jobs that don't block pay nothing. Stored on the native module, so every copy of fibers in a process shares one count.
test/await-continuation-blocks.js Non-blocking awaits → 0; one continuation blocking twice → 1; two blocking continuations → 2; awaits outside a fiber → 0. Prints pass (skips) when dispatch is off.

The labelled metric and the dev-only call-site recorder live in qualialabs/qualia#57387.

Testing

Not run on Node 24: the code is identical to the Node 18 version (cherry-picked; the only conflict was next to the AsyncContextFrame probe). Results from the Node 18 build:

  • test/await-continuation-blocks.js: pass by default, with FIBERS_AWAIT_REUSE=0 (one-off dispatch path), and with FIBERS_AWAIT_DISPATCH=0 (skips).
  • Microbenchmark: 5,000 blocking continuations × 12 runs → Fiber.awaitContinuationBlocks = 60,000, an exact count.
  • In local qualia the count matched prom-client's labelled metric and the dev-only recorder (4/4 and 3/3).

🤖 Generated with Claude Code

Fiber.awaitContinuationBlocks counts code after an `await` that blocked on
the hidden fiber the dispatcher gave it (Future.wait, Promise.await, a sync
Meteor call). Without the dispatch each of these would have thrown "Can't
wait without a fiber", so the count tracks code that still depends on fibers
after an await. It's counted in the dispatcher's existing "job blocked"
branch, once per job, so jobs that don't block and ordinary yields cost
nothing extra. The count lives on the native module so every copy of
fibers in a process shares it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant