Performance & tuning in nodejs

advance · Node.js — Server-side JavaScript

In Node.js, while the Event Loop handles all asynchronous I/O (like network requests), it is strictly single-threaded. To prevent "blocking" the main thread with heavy operations, Node.js uses a background Thread Pool provided by the libuv C library. 1. What is the libuv Thread Pool? The thread pool is a group of worker threads that perform tasks that cannot be handled asynchronously by the Operating System itself. If JavaScript needs to do something heavy—like encrypting a password or reading a large file—libuv offloads that task to one of these background threads. 2. What tasks go to the Thread Pool? Not everything goes to the thread pool. Node.js distinguishes between Network I/O and File/CPU I/O . Non-Blocking (OS Level): Most network-based tasks (TCP/UDP, DNS lookups) are handled by the OS kernel directly (using epoll/kqueue). These do not use the thread pool. Blocking (Thread Pool Level): The following tasks are sent to libuv workers: File System ( fs ): All synchronous and most asynchronous file operations. Cryptography ( crypto ): Complex math like pbkdf2 , randomBytes , or scrypt . Compression ( zlib ): Tasks like gzip or brotli . DNS: dns.lookup() (because it uses the synchronous system call getaddrinfo ). 3. The Default Size By default, the libuv thread pool has 4 threads . This means if you try to perform 5 heavy cryptographic operations at the exact same time, the first 4 will start immediately, while the 5th one will wait in a queue until one of the first four finishes. Example of a Bottleneck: If you run this code, you’ll notice the first four logs appear at roughly the same time, but the fifth appears a bit later because it had to wait for a free thread: const crypto = require('crypto'); const start = Date.now(); for (let i = 0; i < 5; i++) {   crypto.pbkdf2('password', 'salt', 100000, 512, 'sha512', () => {     console.log(`Task ${i + 1}:`, Date.now() - start, "ms");   }); } 4. Changing the Pool Size You can increase the number of threads if your application performs many heavy disk or crypto operations. This is done by setting the UV_THREADPOOL_SIZE environment variable before the application starts. Max Size: 1024 threads. Optimal Size: Usually matched to the number of logical CPU cores on your server. How to set it: # On Linux/Mac export UV_THREADPOOL_SIZE=8 node app.js # On Windows set UV_THREADPOOL_SIZE=8 && node app.js 5. Why not just make the pool infinite? Adding more threads isn't always better. Context Switching: The CPU has to spend time switching between threads. If you have 1,000 threads but only 4 CPU cores, the overhead of switching will actually make the app slower. Memory: Each thread consumes a certain amount of RAM for its own stack. Feature Event Loop libuv Thread Pool Quantity 1 (Single-threaded) Default 4 (Configurable) Handles Fast I/O, Callbacks, Timers Heavy I/O, Crypto, File Ops Handles Blocks the whole app Only blocks its specific thread Nature Continuous loop Worker queue

Back to Node.js — Server-side JavaScript

Browse all study material on Careeroza