How does the Nodejs do i/o under the hood?

Solution 1:

File IO in nodejs uses a thread pool. By default, there are 4 threads in the pool.

When some Javascript calls a file operation such as fs.open() in nodejs, the call is routed to some native code within the libuv library in the nodejs implementation. That code adds the specific file operation to a queue of items waiting for an OS thread. If an OS thread is immediately available, then that OS thread is given the task of carrying out the file operation and then the original libuv function returns which returns back to the original Javascript and nodejs continues running other Javascript.

Then, sometime later the thread finishes the file operation and has a result. It inserts an event into the nodejs event queue with the completed result and the original callback passed with the original file operation.

When nodejs has finished executing any other Javascript it was running, it pulls the next event from the event queue and calls the Javascript callback associated with that event and passes it the data associated with the event. This triggers the Javascript callback that was originally passed to fs.open() to get called.

If, in the second step above, there were no available threads in the thread pool, then the task is added to a queue and libuv immediately returns control back to nodejs so it can run other Javascript. Sometime later when one of the existing threads in the pool completes and finishes its work of adding an event to the event queue, then it will pull the next item out of the the thread pool queue, give it the now-available thread and let it start running its operation.

In this way, all file operations appear to be non-blocking and asynchronous from the Javascript side of things. They either get started immediately if there is an available thread in the thread pool or they sit in a thread pool queue until a thread is available. That part is invisible to the Javascript side of things. Either way, the operation is initiated or queued and control immediately returns back to nodejs to continue running other Javascript. And, either way, the operation completes sometime later and the Javascript callback associated with the file operation gets called via the Javascript event queue. This provides the asynchronous, non-blocking, event-driven mechanism that nodejs uses for all file I/O.