1 const crypto
= require('node:crypto')
2 const assert
= require('node:assert')
3 const fs
= require('node:fs')
4 const Benchmark
= require('benchmark')
12 WorkerChoiceStrategies
,
14 } = require('../lib/index.js')
15 const { TaskFunctions
} = require('./benchmarks-types.js')
17 const buildPoolifierPool
= (workerType
, poolType
, poolSize
, poolOptions
) => {
21 case WorkerTypes
.thread
:
22 return new FixedThreadPool(
24 './benchmarks/internal/thread-worker.mjs',
27 case WorkerTypes
.cluster
:
28 return new FixedClusterPool(
30 './benchmarks/internal/cluster-worker.js',
35 case PoolTypes
.dynamic
:
37 case WorkerTypes
.thread
:
38 return new DynamicThreadPool(
39 Math
.floor(poolSize
/ 2),
41 './benchmarks/internal/thread-worker.mjs',
44 case WorkerTypes
.cluster
:
45 return new DynamicClusterPool(
46 Math
.floor(poolSize
/ 2),
48 './benchmarks/internal/cluster-worker.js',
56 const runPoolifierPool
= async (pool
, { taskExecutions
, workerData
}) => {
57 return await
new Promise((resolve
, reject
) => {
59 for (let i
= 1; i
<= taskExecutions
; i
++) {
64 if (executions
=== taskExecutions
) {
77 const runPoolifierPoolBenchmark
= async (
82 { taskExecutions
, workerData
}
84 return await
new Promise((resolve
, reject
) => {
85 const pool
= buildPoolifierPool(workerType
, poolType
, poolSize
)
86 const suite
= new Benchmark
.Suite(name
)
88 for (const workerChoiceStrategy
of Object
.values(
89 WorkerChoiceStrategies
91 for (const enableTasksQueue
of [false, true]) {
92 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
93 for (const measurement
of [
98 `${name} with ${workerChoiceStrategy}, with ${measurement} and ${
99 enableTasksQueue ? 'with' : 'without'
102 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
, {
105 pool
.enableTasksQueue(enableTasksQueue
)
107 pool
.opts
.workerChoiceStrategy
,
111 pool
.opts
.enableTasksQueue
,
115 pool
.opts
.workerChoiceStrategyOptions
.measurement
,
118 await
runPoolifierPool(pool
, {
127 `${name} with ${workerChoiceStrategy} and ${
128 enableTasksQueue ? 'with' : 'without'
131 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
132 pool
.enableTasksQueue(enableTasksQueue
)
134 pool
.opts
.workerChoiceStrategy
,
137 assert
.strictEqual(pool
.opts
.enableTasksQueue
, enableTasksQueue
)
138 await
runPoolifierPool(pool
, {
148 .on('cycle', event
=> {
149 console
.info(event
.target
.toString())
151 .on('complete', function () {
154 LIST_FORMATTER
.format(this.filter('fastest').map('name'))
156 const destroyTimeout
= setTimeout(() => {
157 console
.error('Pool destroy timeout reached (30s)')
165 clearTimeout(destroyTimeout
)
169 .run({ async
: true })
181 const LIST_FORMATTER
= new Intl
.ListFormat('en-US', {
186 const generateRandomInteger
= (max
= Number
.MAX_SAFE_INTEGER
, min
= 0) => {
187 if (max
< min
|| max
< 0 || min
< 0) {
188 throw new RangeError('Invalid interval')
190 max
= Math
.floor(max
)
191 if (min
!= null && min
!== 0) {
193 return Math
.floor(Math
.random() * (max
- min
+ 1)) + min
195 return Math
.floor(Math
.random() * (max
+ 1))
198 const jsonIntegerSerialization
= n
=> {
199 for (let i
= 0; i
< n
; i
++) {
209 * Intentionally inefficient implementation.
210 * @param {number} n - The number of fibonacci numbers to generate.
211 * @returns {number} - The nth fibonacci number.
213 const fibonacci
= n
=> {
215 return fibonacci(n
- 1) + fibonacci(n
- 2)
219 * Intentionally inefficient implementation.
220 * @param {number} n - The number to calculate the factorial of.
221 * @returns {number} - The factorial of n.
223 const factorial
= n
=> {
227 return factorial(n
- 1) * n
230 const readWriteFiles
= (
232 baseDirectory
= `/tmp/poolifier-benchmarks/${crypto.randomInt(
236 if (fs
.existsSync(baseDirectory
) === true) {
237 fs
.rmSync(baseDirectory
, { recursive
: true })
239 fs
.mkdirSync(baseDirectory
, { recursive
: true })
240 for (let i
= 0; i
< n
; i
++) {
241 const filePath
= `${baseDirectory}/${i}`
242 fs
.writeFileSync(filePath
, i
.toString(), {
246 fs
.readFileSync(filePath
, 'utf8')
248 fs
.rmSync(baseDirectory
, { recursive
: true })
252 const executeTaskFunction
= data
=> {
253 switch (data
.function) {
254 case TaskFunctions
.jsonIntegerSerialization
:
255 return jsonIntegerSerialization(data
.taskSize
|| 1000)
256 case TaskFunctions
.fibonacci
:
257 return fibonacci(data
.taskSize
|| 1000)
258 case TaskFunctions
.factorial
:
259 return factorial(data
.taskSize
|| 1000)
260 case TaskFunctions
.readWriteFiles
:
261 return readWriteFiles(data
.taskSize
|| 1000)
263 throw new Error('Unknown task function')
270 generateRandomInteger
,
271 runPoolifierPoolBenchmark