Why does fs.readFile complete in the first thread-pool wave, ahead of pbkdf2 tasks queued before it? #5161
Replies: 1 comment
|
It is not really that
So the ordering guarantee you were expecting is stronger than what the thread pool gives you. Submission order affects when work can start, but callback order is completion order, not submission order. A couple of details make this more visible here:
If you want to sanity-check the model, try two experiments:
With one worker, the filesystem task has much less opportunity to finish beside the second PBKDF2 wave, so the output should look much closer to strict serialization. And then increase the PBKDF2 iterations heavily. The The source trail to look at is Node's async crypto PBKDF2 binding queuing work into libuv, Node's fs bindings for async fs requests, and libuv's threadpool worker queue / completion queue. The key distinction is queue/start order versus completion/callback order. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
With the default libuv thread pool size (4), I fire six
crypto.pbkdf2()calls and onefs.readFile()of a small, already-cached file in the same synchronous tick. The six pbkdf2 calls are issued before thefs.readFilecall. I expected thereadFilecallback to complete after the pbkdf2 work, but it consistently lands in the first wave of completions, while two of the pbkdf2 tasks are pushed to a later wave.Environment
UV_THREADPOOL_SIZE: unset (default 4)Reproduction
Observed output
The four-then-two split for the pbkdf2 tasks matches the 4-thread pool as expected.
Question
Given that all six pbkdf2 calls are submitted before
fs.readFilein the same tick, why does thereadFilecallback complete in the first wave (~24ms) rather than after pbkdf2 5 and 6?I'm trying to build an accurate mental model of how the thread pool orders and schedules this work. A pointer to where in the source this ordering is determined would be much appreciated. Thanks!
All reactions