Reputation: 171
Node.js maintains an event loop but then it also has by default four threads for the complicated requests. How this is single threaded when there are more threads available in the thread pool?
Also, the threads assigned by the event loop for the complicated task are the dedicated threads then how it's different from other multithreading concepts?
Upvotes: 17
Views: 6450
Reputation: 2755
I will tell it in a clear and simple way and clear the confusion:
Node's event loop is SINGLE-THREADED but the other processes are NOT.
The confusion came from C++, which Node uses under the hood (NodeJS is about 30% JS + 70% C++). So, by default the JS part of NodeJS is single-threaded BUT it uses a thread pool of C++. So, we have a single threaded JS which is the event loop of NodeJS + 4 threads of C++ if needed for asynchronous I/O operations.
It is also important to know that the event loop is like a traffic organizer, every request goes through the loop (which is single-thread). The event loop then organizes those requests to the pool threads if I/O processes are needed. If you have a high computational tasks like heavy lifting image-processing, video-editing, audio-processing or 3d-graphics, etc. (which is not needed for most apps), then NodeJS will be a bottleneck for you. NodeJS shines for I/O bound apps (which is the case with most apps) that perform tasks like dealing with databases and filesystem.
Again, by default, NodeJS uses a 4 thread pool (PLUS one thread for the event loop itself) - a total of 5 threads.
As a general idea, the CPU could contain one or more cores, it depends on your server(money).
Each core could have threads. Watch your activity monitor and discover how many threads you are using.
Each process has multiple threads.
The multi-threading of Node is because node depends on V8 and libuv (C Library).
So long story short -
Node is single-threaded for the event loop itself but there are many operations that are done outside the event loop(like crypto and file system). If you have two calls for crypto then each of them will reach a THREAD (imagine 3 calls to crypto and 1 for fs, these calls will be distributed one for each thread from the 4 threads in the thread pool).
Finally: It is very easy to increase the default number of threads of the C-Library libuv thread pool which is 4 by default by changing the value of process.env.uv_threadpool_size. And also you could use clustering (PM2 recommended) to clone the event-loop and have multiple event-loops in case the single-threaded one is not enough for your computationally heavy app.
So nobody illustrates that thread pool is a C++ thing that’s in control of NodeJS and mostly not meant to be controlled by the developer.
Hope that simplifies things.
Upvotes: 10
Reputation: 13
For async processing, Node.js was created explicitly as an experiment. It is believed that more performance and scalability can be achieved by doing async processing on a single thread under typical web loads than the typical thread based implementation.
Upvotes: 1
Reputation: 707228
In the context to which you're referring, "single threaded" means that your Javascript runs as a single thread. No two pieces of Javascript are ever running at the same time either literally or time sliced (note: as of 2020 node.js does now have WorkerThreads, but those are something different from this original discussion). This massively simplifies Javascript development because there is no need to do thread synchronization for Javascript variables which are shared between different pieces of Javascript because only one piece of Javascript can ever be running at the same time.
All that said, node.js does use threads internal to its implementation. The default four threads you mention are used in a thread pool for disk I/O. Because disk I/O is normally a synchronous operation at the OS level that blocks the calling thread and node.js has a design where all I/O operations should be offered as asynchronous operations, the node.js designers decided to fulfill the asynchronous interface by using a pool of threads in order to implement (in native code), the fs module disk I/O interface (yes there are non-blocking disk I/O operations in some operating systems, but the node.js designers decided not to use them). This all happens under the covers in native code and does not affect the fact that your Javascript runs only in a single thread.
Here's a summary of how a disk I/O call works in node.js. Let's assume there's already an open file handle.
fs.write()
on an existing file handle.fs.write()
callfs.write()
callfs.write()
call on a thread finishes. It obtains a mutex protecting the event loop and inserts an event in the event queue.Because a new event is never acted upon until the current stream of Javascript is done executing, this is where Javascript gets is event-driven, single threaded nature even though native code threads may be used to implement some library functions. Those threads are used to make a blocking operation into a non-blocking operation, but do not affect the single threaded-ness of Javascript execution itself.
The key here is that node.js is event driven. Every new operation that triggers some Javascript to run is serialized through the event queue and the next event is not serviced until the current stream of Javascript has finished executing.
In the node.js architecture the only way to get two pieces of Javascript to run independently and at the same time is to use a separate node.js process for each. Then, they will run as two completely separate operations and the OS will manage them separately. If your computer has at least two cores, then they can literally run at the same time, each on their own core. If your computer has only one core, they will essentially be in their own process thread and the OS will time slice them (sharing the one CPU between them).
Upvotes: 17
Reputation: 17710
By default, the execution of your JavaScript code runs on a single thread.
However, node.js tries to make most long-running calls async. For some that just involves doing async OS calls, but for some others node.js will execute the call itself on a secondary thread, while continuing to run other JS code. Once the async call terminated, the Js callback or Promise handler will run.
Upvotes: 2