When a Node.js process is spun up top command shows 7 threads attached to the process. What are all these threads doing? Also, as the load on the API increases, with the request handlers themselves asynchronously awaiting other upstream API calls does Node spawn additional worker threads? I see in top that it does that. But I was thinking this only happens for file I/o. Why does it need these additional worker threads?
1 Answers
LIBUV (the underlying cross platform system library that node.js is built-on) uses a thread pool for certain operations such as disk I/O and some crypto operations. By default that thread pool contains 4 threads.
Plus, there is a thread for the execution of your Javascript so that accounts for 5.
Then, it appears there is a thread used by the garbage collector for background marking of objects (per this reference from a V8 developer) and this article. That would make 6.
I don't know for sure what the 7th one would be. It's possible there's a thread used by the event loop itself.
Then, starting some time around 2018, it appears that nodejs switched to a separate set of threads for DNS requests (separate from the file I/O thread pool). This was probably because of problems in node.js where 4 slow DNS requests could block all file I/O because they took over the thread pool. So, now it looks like node.js used the C-ARES library for DNS which makes its own set of threads.
FYI, you can actually control the thread pool size with the UV_THREADPOOL_SIZE
environment variable.
And, of course, you can create your own Worker Threads that actually create new instances of the V8 Javascript execution engine (so they will likely end up creating more than one new thread).

- 683,504
- 96
- 985
- 979
-
Thanks. I get the libuv thread pool part. I am looking to understand what all these Threads are there for. For example on Node 12.6.2 I ran a couple of tests with heavy network I/O (This Node API calls another Node API with a high latency) and without. In the test without network I/O Node spun 7 threads of which 4 seem to be node::PlatformWorkerThread (So these must be the default 4 worker threads in the libuv thread pool). In the test with Network I/O Node spun 11 threads of which again 4 are node::PlatformWorker thread and 4 others are labeled as worker (in node) that were doing DNS lookups. – cubsnlinux May 02 '20 at 00:20
-
So what is the difference between node::PlatformWorkerThread and "worker (in node)" threads? If the node::PlatformWorkerThread threads are not doing DNS lookups during Network I/O (Which I thought they would as they seem to be part of the libuv thread pool) what are they for? – cubsnlinux May 02 '20 at 00:26
-
@cubsnlinux - I don't know the difference between those two off the top of my head. If one wanted to know, you can go look at DNS requests in the [node source](https://github.com/nodejs/node) and see how they work. I do remember reading that DNS requests also use native threads, but I don't know if they use the regular thread pool or have their own thread pool. – jfriend00 May 02 '20 at 17:31
-
@cubsnlinux - After a little research, I found several 2018 references that say the DNS lookups use the regular libuv thread pool and actually compete with file I/O for those threads. I have not found any references that would explain those other types of threads you saw unless DNS was changed since 2018 to use its own thread pool (which is possible). Ultimately, this could be figured out by studying the node.js DNS code (I don't have ability to do that at the moment). – jfriend00 May 02 '20 at 17:40
-
@cubsnlinux - More current [references](https://itnext.io/an-intro-to-node-js-that-you-may-have-missed-b175ef4277f7) say that DNS uses the [c-ares library](https://c-ares.haxx.se/) for DNS that sounds like it's a separate set of worker threads from the file I/O worker pool. I tried looking in the source code and there are definitely references to `cares` as a library, but I was unable to understand the code well enough to see it actually make separate threads. But, the reference to `cares` in the source does line up with what the above article says. – jfriend00 May 02 '20 at 18:30
-
that’s awesome, thanks. It looks like most probably Node.js uses a separate thread pool for DNS lookups. The PlatformWorker threads seem to be ones coming out of libuv. I will do some file I/o ops and will do a thread dump to confirm. – cubsnlinux May 03 '20 at 14:26