Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between single thread and non-blocking I/O operation in NodeJs?

Tags:

node.js

I've been reading up and going through as much of NodeJs code as I can but I'm a bit confused about this:

What exactly does Node being single threaded mean and what does non-blocking I/O mean? I can achieve the first one by spawning a child process and the second one by using async library. But I wanted to be clear what it meant and how non-blocking I/O can still slow up your app.

like image 597
Hick Avatar asked Jun 04 '13 22:06

Hick


People also ask

What is the difference between blocking and non-blocking in Node JS?

Blocking methods execute synchronously and non-blocking methods execute asynchronously. And here is an equivalent asynchronous example: const fs = require('fs'); fs.

What are the differences between a blocking I/O and a non-blocking IO?

Blocking - Linear programming, easier to code, less control. Non-blocking - Parallel programming, more difficult to code, more control.

What is the difference between asynchronous and non-blocking Node JS?

Non-Blocking: It refers to the program that does not block the execution of further operations. Non-Blocking methods are executed asynchronously. Asynchronously means that the program may not necessarily execute line by line.

What do you mean by single threaded non-blocking IO?

Non-blocking operation means the server will not block itself for one request. Non-blocking call only initiates the operation and the response is provided later, meanwhile, it can continue with other client requests.


1 Answers

I'll try my best to explain.

Single-threaded means that the Node.js Javascript runtime - at a particular point in time - only is executing one piece of code from all the code it has loaded. In effect, it starts somewhere, and works it way down through all instructions (the call stack) until it's done. While it's executing code, nothing can interrupt this process, and all I/O must wait. Thankfully, most call stacks are relatively short, and lots of things we do in Node.js are more of the "bookkeeping" type than CPU-heavy.

Being single-thread though, any instructions that would take a long time would be a huge problem for the responsiveness in a system. The runtime can only do one thing at a time, so everything must wait until that instruction has finished. If any "I/O" instruction (say reading from disk) would block execution, then the system would be unnecessarily unavailable at that time.

But thankfully, we've got non-blocking I/O.

Instead of waiting for a file to be read:

console.log(readFileSync(filePath))

you write your code so that you DON'T wait for a file to be read:

readFile(filePath)

The readFile call returns almost instantly (perhaps in a a few nano-seconds), so the runtime can continue executing instructions that come next. But if the readFile call returns before the data has been read, there's no way that the the readFile call can return the file contents. That's where callbacks come in:

readFile(filePath, function(err, contents) { console.log(contents))

Still, the readFile call returns almost instantly. The runtime can continue. It will finish the current work before it (all instructions coming after readFile). Nothing is done with the function that's passed, other than storing a reference to it.

Then, at some later point in time (perhaps 10ms, 100ms, or 1000ms later) when reading the file has completed, the callback is called with as second argument the full contents of the file. Before that time, any number of other batches of work could have been done by the runtime.

Now I will address your comments about spawning child processes and Async library. You are wrong on both accounts.

  • Spawning a child process is a way to let Node.js use more than CPU core. Being single-threaded, a single Node.js has no purpose for using more than one core. Still, if you are on a multi-core computer, you may want to use all those cores. Hence, start multiple Node.js. processes.

  • The Async library will not give you non-blocking I/O, Node.js gives you that. What Node.js does not give you itself, is an easy way to deal with data coming in from multiple callbacks. The Async library can help a great deal with that.

As I'm not an expert on Node.js internals, I welcome corrections!

Related questions:

  • asynchronous vs non-blocking
  • What's the difference between: Asynchronous, Non-Blocking, Event-Base architectures?
like image 193
Myrne Stol Avatar answered Nov 01 '22 05:11

Myrne Stol