1

I've written a Nodejs C++ module that makes use of NAN's AsyncWorker to expose async module functionality. Works great. However, I understand that AsyncWorker makes use of libuv's thread pool, which defaults to just 4 threads.

While this (or a #-of-cores based limitation) might make sense for CPU-heavy functions, some of my exposed functions may run relatively long, even though they don't use the CPU (network activity, etc). Therefore the thread pool might get all used up even though no computation-intensive work is going on.

The easy solution is to increase the thread pool size (UV_THREADPOOL_SIZE). However, I am concerned that this thread pool is used for other things as well, which might suffer from a performance hit due to too much parallelization (the libuv documentation states, "The threadpool is global and shared across all event loops...").

Is my concern valid? Is there a way to make use of a separate, larger, thread pool only for certain AsyncWorker's that are long-running but not CPU-intenstive, while leaving the common thread-pool untouched?

simon-p-r
  • 3,623
  • 2
  • 20
  • 35
logidelic
  • 1,525
  • 15
  • 42
  • What do you mean by "wait for other work to complete"? They should be doing this in a way that doesn't block the thread. – Lou Franco Mar 27 '17 at 14:21
  • AsyncWorker offloads work from the main thread to a worker thread exactly so that nothing done blocks the main (node) thread. That's not the issue. The issue is that a thread pool of 4 threads is made use of (by default) such that no more than 4 AsyncWorker's can be run in parallel. – logidelic Mar 27 '17 at 14:34
  • I am talking about waits that happen on the worker threads. Are you also doing those in a non-blocking way so that the thread is returned to the pool? – Lou Franco Mar 27 '17 at 14:39
  • That is not how AsyncWorker is meant to be used. Imagine exposing something like `uploadfile(filename, cb)` where `cb` gets called upon success or failure ... This is typical of all async functions and is exactly what AsyncWorker is helping us encapsulate. The upload itself may take several seconds. This _must_ block AsyncWorker's allocated thread (i.e. `AsyncWorker::Execute()`) in some way. That's just the way AsyncWorker is designed. Once `AsyncWorker::Execute()` exits, the thread is returned to the pool and then the callback can be performed in the main nodejs thread. – logidelic Mar 27 '17 at 14:45
  • My cursory glance at the nan docs makes me think that this is incompatible with work that goes into wait states. I think your concerns are valid, and just increasing the thread-pool feels like the wrong solution to me. I think you need a different async abstraction or perhaps you can build on this -- return from execute, but somehow kickoff another worker when the thing you were waiting for is ready. – Lou Franco Mar 27 '17 at 15:18
  • You may be right. If so I have a feeling that a lot of module developers would be surprised to understand this. Writing a variation of AsyncWorker (AsyncLongRunWorker) which supports long running operations isn't too difficult, so I might just do that. – logidelic Mar 27 '17 at 15:44

0 Answers0