WittCode💻

Maximizing Node's Performance with Threads

By

Learn how to maximize the performance of a Node application using threads. We will discuss how Node uses a threadpool, the libuv C library, and Node's single threaded nature.

Table of Contents 📖

Is Node Single Threaded?

Node is single threaded, but it offloads certain tasks to a threadpool. This allows Node to keep its event loop (the main single thread) free to handle other requests/tasks. Example tasks offloaded to a threadpool are file system I/O, cryptographic functions, and DNS lookups.

const fs = require('fs/promises');

async function readFileAsync() {
  try {
    console.log('Starting file read');
    
    // Await the file read operation
    const data = await fs.readFile('example.txt', 'utf8');
    
    console.log('File content:', data);
  } catch (err) {
    console.error('Error reading file:', err);
  }
}

readFileAsync();
console.log('File read operation initiated');

Node's threadpool is provided by libuv, a C library that powers Node under the hood. Configuring this threadpool can significantly enhance a Node app's performance.

Configuring the Threadpool

The threadpool provided by libuv can become saturated. When this happens, tasks must wait in a queue which can cause performance issues. Because of this, we can set the size of the libuv threadpool with the environment variable UV_THREADPOOL_SIZE. We can set this variable using the command line when starting a a Node process. The example below will set the size of the threadpool to 8 threads.

UV_THREADPOOL_SIZE=8 node app.js

The default threadpool size is 4, but it can be increased up to 128. Nevertheless, the max technically depends on the system's resources.

ERROR: While increasing the thread pool size can improve performance, over-allocation can result in excessive context switching, reducing efficiency.

How to Tune the Threadpool

Deciding the proper amount of threads will come from analyzing system metrics and performance. One approach is to gradually increase the threadpool size and observe the impact. Just make sure the tests mimic the real world conditions as closely as possible.