| 1 | # General guidelines |
| 2 | |
| 3 | Performance is one of the main target of these worker pool implementations, poolifier team wants to have a strong focus on this. |
| 4 | Poolifier already has [benchmarks](./../benchmarks/README.md) where you can find some comparisons. |
| 5 | |
| 6 | ## Table of contents |
| 7 | |
| 8 | - [Internal Node.js thread pool](#internal-nodejs-thread-pool) |
| 9 | - [Cluster vs Threads worker pools](#cluster-vs-threads-worker-pools) |
| 10 | - [Fixed vs Dynamic pools](#fixed-vs-dynamic-pools) |
| 11 | |
| 12 | ## Internal Node.js thread pool |
| 13 | |
| 14 | Before to jump into each poolifier pool type, let highlight that **Node.js comes with a thread pool already**, the libuv thread pool where some particular tasks already run by default. |
| 15 | Please take a look at [which tasks run on the libuv thread pool](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/#what-code-runs-on-the-worker-pool). |
| 16 | |
| 17 | **If your task runs on libuv thread pool**, you can try to: |
| 18 | |
| 19 | - Tune the libuv thread pool size setting the [UV_THREADPOOL_SIZE](https://nodejs.org/api/cli.html#cli_uv_threadpool_size_size). |
| 20 | |
| 21 | and/or |
| 22 | |
| 23 | - Use poolifier cluster pools that are spawning child processes, they will also increase the number of libuv threads since that any new child process comes with a separated libuv thread pool. **More threads does not mean more fast, so please tune your application**. |
| 24 | |
| 25 | ## Cluster vs Threads worker pools |
| 26 | |
| 27 | **If your task does not run into libuv thread pool** and is CPU intensive then poolifier **thread pools** (_FixedThreadPool_ and _DynamicThreadPool_) are suggested to run CPU intensive tasks, you can still run I/O intensive tasks into thread pools, but performance enhancement is expected to be minimal. |
| 28 | Thread pools are built on top of Node.js [worker_threads](https://nodejs.org/api/worker_threads.html) module. |
| 29 | |
| 30 | **If your task does not run into libuv thread pool** and is I/O intensive then poolifier **cluster pools** (_FixedClusterPool_ and _DynamicClusterPool_) are suggested to run I/O intensive tasks, again you can still run CPU intensive tasks into cluster pools, but performance enhancement is expected to be minimal. |
| 31 | Consider that by default Node.js already has great performance for I/O tasks (asynchronous I/O). |
| 32 | Cluster pools are built on top of Node.js [cluster](https://nodejs.org/api/cluster.html) module. |
| 33 | |
| 34 | If your task contains code that runs on libuv plus code that is CPU intensive or I/O intensive you either split it either combine more strategies (i.e. tune the number of libuv threads and use cluster/thread pools). |
| 35 | But in general, **always profile your application**. |
| 36 | |
| 37 | ## Fixed vs Dynamic pools |
| 38 | |
| 39 | To choose your pool consider first that with a _FixedThreadPool_/_FixedClusterPool_ or a _DynamicThreadPool_/_DynamicClusterPool_ your application memory footprint will increase. |
| 40 | By doing so, your application will be ready to execute in parallel more tasks, but during idle time your application will consume more memory. |
| 41 | One good choice from poolifier team point of view is to profile your application using a fixed or dynamic worker pool, and analyze your application metrics when you increase/decrease the number of workers. |
| 42 | For example you could keep the memory footprint low by choosing a _DynamicThreadPool_/_DynamicClusterPool_ with a minimum of 5 workers, and allowing it to create new workers until a maximum of 50 workers if needed. This is the advantage of using a _DynamicThreadPool_/_DynamicClusterPool_. |
| 43 | But in general, **always profile your application**. |