Utilizing Thread pools in Node.js
Explanation of utilizing thread pools with the single-threaded event loop

A lifelong learner. Love to travel. Listen to music.
Search for a command to run...
Explanation of utilizing thread pools with the single-threaded event loop

A lifelong learner. Love to travel. Listen to music.
Best Practices for Path Structure, Versioning, and Error Handling

Understanding the Performance Implications of async and defer Attributes

Overview static: Default position. It does not allow setting properties like top, bottom, left, right, z-index relative: Acts the same as static. but allows positioning it relatively by putting properties like top, bottom, left, right, z-index absolu...

Overview When an element in the browser has a conflict of styles, the browser uses a set of rules to determine which style should be rendered. This set of rules is defined as CSS Selector Specificity. For instance, for an element, if we have the foll...

Master block, inline, flex, and grid to build better web layouts

If you are wondering about the title,
fs module in Node.js use thread poolscrypto module like pbkdf2 hash method use Node.js thread poolWe all know, that Node.js is a single-threaded runtime. Every time we run Node.js, an event loop is created and inside a single thread, it determines what is going to be executed at a single time.
The event loop keeps an eye on the following to keep the loop continuing,
Pending Operations is the one that handles the thread pool. By default, the thread pool keeps managing 4 threads at a time.
Before we proceed further, let's get some memory refreshment of threads and OS Schudling.
When we run the program on the computer, we run Process. Process is an instance of a computer program. Inside a process, there are single/multiple threads.
A thread contains an instruction list like getting a file, reading it, executing an operation, closing the file, etc. These instructions are inside the threads and are usually executed by the CPU.
Usually, an I/O operation requires non-zero time to be completed. Consider the process of reading a file. In this process, there can be two threads, one to get file info from a hard drive and another operation on that file, like reading. OS first tries to get the file info from the disk. This is a time-consuming process. During this waiting time, a CPU can take another thread and return back to the first thread to do the rest of the work.
Observe the following codes,
const start = new Date.now();
function doRequest() {
// making a HTTP request
console.log(`Network: ${Date.now() - start}ms`);
}
function doHash() {
crypto.pbkdf2(...args, () => {
console.log(`Hash: ${Date.now() - start}ms`);
});
}
doRequest();
fs.readFile('fileName', 'format', () => {
console.log(`FS: ${Date.now() - start}ms`);
});
doHash();
doHash();
doHash();
doHash();
Output,
Network: time
Hash: time
FS: time
Hash: time
Hash: time
Hash: time
From the output, a couple of interesting facts come up,
Explanation:
HTTP calls are handled by OS itself. On the other hand, file system operation and hashing operation are handled by the thread pool. So while other operations make it to the thread pool, we get results from the HTTP requests.
For file system operation, there are two distinct processes,
By default, we have 4 threads in the thread pool. We have 5 operations, 1 file system operation, and 4 hash operations. Among them, initially, 1 fs took one thread and 3 hash take other 3 threads.
In the first thread, While we go and look at the info of the file, and wait for info, the one leftover hash took place in the pool. In the meantime, the file stats are ready. The moment one hash is completed, the empty thread takes the leftover file operation and makes it completed almost immediately.
We can control the number of pools in
thred-poolsusingUV_THREADPOOL_SIZEenvironment variable
Now if we make the thread pool size 5,
process.env.UV_THREADPOOL_SIZE = 5;
const start = new Date.now();
function doRequest() {
// making a http request
console.log(`HTTP: ${Date.now() - start}ms`);
}
function doHash() {
crypto.pbkdf2(...args, () => {
console.log(`Hash: ${Date.now() - start}ms`);
});
}
doRequest();
fs.readFile('fileName', 'format', () => {
console.log(`FS: ${Date.now() - start}ms`);
});
doHash();
doHash();
doHash();
doHash();
The output will be,
FS: time
Network: time
Hash: time
Hash: time
Hash: time
Hash: time
Hope this makes sense. Network calls are handled by OS, and do not deal with a thread pool. In the thread pool, for 5 operations (4 hashing and one file operation). With 5 threads, all operations come at the same time and file operation is faster than others. Network calls, handled by OS itself, are faster than the hashing operation and come at next. Then all other hash operations output comes in a sequence.
What if, the thread pool size is 1?
Network: time
Hash: time
Hash: time
Hash: time
Hash: time
FS: time
Hope this makes sense,
So yes, the event loop is single-threaded and internally, with libUV it makes use of multiple threads.
References: Node JS: Advanced Concepts By Stephen Grider