Is NodeJs Single Threaded – Let’s Find Out

NodeJS is single threaded, hmm yes but this is a partial truth, actually it is event-driven and single-threaded with background workers. NodeJS is based on  JavaScript and C++.  JavaScript executes on the server by google chrome v8 engine and libuv library, written in C++, take care of non-blocking I/O through background workers.

 How Threads Work In NodeJS

What makes NodeJS unique is the way in which it manages event-driven asynchronous operations for us and this where the concept of an Event Loop comes into the picture.

var sockets = require('websocket.io'),httpServer = sockets.listen(4000);

 httpServer.on('onConnection', function (socket) {   

   console.log('connected……');

   httpServer.send('Web socket connected.'); 

    httpServer.on('message', function (data) {

                         console.log('message received:', data);

   });

      httpServer.on('close', function () {
                         console.log('socket closed!');
    });
  });

In above code snippet, as soon as ws.listen(4000) executes, a Web-Socket server is created on a single thread – event loop  which listens continuously on port 4000. When a client connects to it, it fires the ‘onConnection’ event which the loop picks up and immediately publishes to the thread pool and is ready to receive the next request.

And this is where NodeJS based server different from IIS/ Apache and the basic difference is that NodeJS do not create new threads for every incoming request but receive all requests of single thread and pass these work items to background workers if required. These workers managed through libuv library and Operating System.

In simple words if my NodeJS server receives 100 requests simultaneously, they all will be received by single event loop thread and then they can be passed to background workers, which actually execute it. When the worker finishes its execution, registered success callback will be invoked again on event loop thread to pass the result back to the user.

Let‘s try with another in-depth example:   We basically need to understand how NodeJS executes the code. NodeJS execution model is different from runtime environments like Python, Ruby, C# or Java.

NodeJS Execution Model
NodeJS Execution Model

Let’s take a very simple piece of code like this:

var queryResult = db.query("select * from mytable");
console.log("Executed………….");

The first line queries a database for lots of rows, the second line puts “Executed ………” to the console. Let’s assume that the database query is quite slow, that it has to read a lot of rows, which takes noticeable time. The way we have written this code, the JavaScript interpreter of NodeJS first has to read the complete result set from the database, and then it can execute the console.log() function. During the time of this query execution, our server will not able to process any further request as this all operation is going on NodsJS event loop thread ( 1 in above figure).

If this piece of code actually was C#, it would work the same way and would take approx. same amount of time but it would not block any other user or in other words  it would not block the request receiver server  as IIS assigned a new thread to every request and this request execute independently.

But the execution model of Node.js is different and there is only one single process to receive the requests and if this process blocked, it would not able to receive new requests until it get unblocked from its ongoing task. If there is a slow database query somewhere in this process, this affects the whole process – everything comes to a halt until the slow query has finished.

To avoid this, we can rewrite our code:

db.query("select * from mytable", function(rows) {
var result = rows;
});
console.log("Hello World");

Here, instead of expecting database.query() to directly return the result to us, we pass it as a second parameter, an anonymous function. In its previous form, our code was synchronous: first do the database query and wait for its completion, and only when this is done, then write to the console. Now, NodeJS can handle the database request asynchronously and delegate this task to workers as shown in (2 in above figure). Provided that database.query() is part of an asynchronous library and now instead of waiting for it to be finished, it makes a contract which says “When database query will be executed, I have to execute the anonymous function that was passed to database.query().” Then, it immediately executes console.log(), and enters into the event loop. NodeJS continuously cycles through this loop waiting for events. Completion of the database query is also an event published to the event loop.

How to increase the number of background threads 

The libuv library manage threads pool that is used by NodeJS to perform long-running operations in the background, without blocking its main thread as we discussed above. We can visit here to more details of LIBUV.

The thread pool is used through submitting a work request to a queue and it contains:

  • A function to execute in the worker thread.
  • A structure for result data.
  • A function to collect the processed results.

This thread pool works as any other standard pooling works. It has some limited amount of threads and these threads allocated to in coming requests. If all threads are busy, the new request will have to wait for its turn.

process.env.UV_THREADPOOL_SIZE =12;

By default size of libuv’s thread pool is 4. We can set number of background threads with UV_THREADPOOL_SIZE environment variable. We cannot change thread pool size once it is created and it is created on the first request.

Although I am a novice in NodeJS world but still I hope the post provide you some insight for NodeJS and its execution model. I would sincerely appreciate your inputs as comments and feedback to enhance the quality of the post.

 

 

Recommended -

Subscribe
Notify of
guest
9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Amit
Amit
9 years ago

Hello Rahul,

This is really helpful for experienced or novice both. Great Article, keep posting more. Ton of Thanks.

rahul garg
rahul garg
9 years ago
Reply to  Amit

I glad it helped you.

Shea
Shea
9 years ago

I am have been looking for and read many other explainations on this subject recently as part of a college project and yours is by far the best.

rahul garg
rahul garg
9 years ago
Reply to  Shea

Thanks Shea !!!

Brandon B.
Brandon B.
8 years ago

I really like the post. However, I think that select statement will not work – “select * f[ro]m mytable”

rahul garg
rahul garg
8 years ago
Reply to  Brandon B.

Thanks for pointing out.

Agarwal Peeyush
Agarwal Peeyush
8 years ago

Hello Rahul.. This is too good but I want to one thing that how this server handles several request with single thread internally?

rahul garg
rahul garg
8 years ago

Sorry for long delay to reply. By default nodeJs initialize one thread (event loop thread) per cpu. This single thread just work to receive and to reply, while any manipulation, network call and other resource intensive work delegated to background workers. As soon as background workers finish their work, they post responce to the event loop thread and thus response will be returned to user.

Matheus
Matheus
7 years ago

Thanks. I figured out now how the event-loop is not blocking-thread.

9
0
Would love your thoughts, please comment.x
()
x
Index