1 const { randomInt
} = require('node:crypto')
2 const { strictEqual
} = require('node:assert')
10 const Benchmark
= require('benchmark')
18 WorkerChoiceStrategies
,
20 } = require('../lib/index.js')
21 const { TaskFunctions
} = require('./benchmarks-types.js')
23 const buildPoolifierPool
= (workerType
, poolType
, poolSize
, poolOptions
) => {
27 case WorkerTypes
.thread
:
28 return new FixedThreadPool(
30 './benchmarks/internal/thread-worker.mjs',
33 case WorkerTypes
.cluster
:
34 return new FixedClusterPool(
36 './benchmarks/internal/cluster-worker.js',
41 case PoolTypes
.dynamic
:
43 case WorkerTypes
.thread
:
44 return new DynamicThreadPool(
45 Math
.floor(poolSize
/ 2),
47 './benchmarks/internal/thread-worker.mjs',
50 case WorkerTypes
.cluster
:
51 return new DynamicClusterPool(
52 Math
.floor(poolSize
/ 2),
54 './benchmarks/internal/cluster-worker.js',
62 const runPoolifierPool
= async (pool
, { taskExecutions
, workerData
}) => {
63 return await
new Promise((resolve
, reject
) => {
65 for (let i
= 1; i
<= taskExecutions
; i
++) {
70 if (executions
=== taskExecutions
) {
83 const runPoolifierPoolBenchmark
= async (
88 { taskExecutions
, workerData
}
90 return await
new Promise((resolve
, reject
) => {
91 const pool
= buildPoolifierPool(workerType
, poolType
, poolSize
)
92 const suite
= new Benchmark
.Suite(name
)
94 for (const workerChoiceStrategy
of Object
.values(
95 WorkerChoiceStrategies
97 for (const enableTasksQueue
of [false, true]) {
98 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
99 for (const measurement
of [
100 Measurements
.runTime
,
104 `${name} with ${workerChoiceStrategy}, with ${measurement} and ${
105 enableTasksQueue ? 'with' : 'without'
108 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
, {
111 pool
.enableTasksQueue(enableTasksQueue
)
113 pool
.opts
.workerChoiceStrategy
,
116 strictEqual(pool
.opts
.enableTasksQueue
, enableTasksQueue
)
118 pool
.opts
.workerChoiceStrategyOptions
.measurement
,
121 await
runPoolifierPool(pool
, {
130 `${name} with ${workerChoiceStrategy} and ${
131 enableTasksQueue ? 'with' : 'without'
134 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
135 pool
.enableTasksQueue(enableTasksQueue
)
137 pool
.opts
.workerChoiceStrategy
,
140 strictEqual(pool
.opts
.enableTasksQueue
, enableTasksQueue
)
141 await
runPoolifierPool(pool
, {
151 .on('cycle', event
=> {
152 console
.info(event
.target
.toString())
154 .on('complete', function () {
157 LIST_FORMATTER
.format(this.filter('fastest').map('name'))
159 const destroyTimeout
= setTimeout(() => {
160 console
.error('Pool destroy timeout reached (30s)')
168 clearTimeout(destroyTimeout
)
172 .run({ async
: true })
184 const LIST_FORMATTER
= new Intl
.ListFormat('en-US', {
189 const generateRandomInteger
= (max
= Number
.MAX_SAFE_INTEGER
, min
= 0) => {
190 if (max
< min
|| max
< 0 || min
< 0) {
191 throw new RangeError('Invalid interval')
193 max
= Math
.floor(max
)
194 if (min
!= null && min
!== 0) {
196 return Math
.floor(Math
.random() * (max
- min
+ 1)) + min
198 return Math
.floor(Math
.random() * (max
+ 1))
201 const jsonIntegerSerialization
= n
=> {
202 for (let i
= 0; i
< n
; i
++) {
212 * Intentionally inefficient implementation.
213 * @param {number} n - The number of fibonacci numbers to generate.
214 * @returns {number} - The nth fibonacci number.
216 const fibonacci
= n
=> {
218 return fibonacci(n
- 1) + fibonacci(n
- 2)
222 * Intentionally inefficient implementation.
223 * @param {number} n - The number to calculate the factorial of.
224 * @returns {number} - The factorial of n.
226 const factorial
= n
=> {
230 return factorial(n
- 1) * n
233 const readWriteFiles
= (
235 baseDirectory
= `/tmp/poolifier-benchmarks/${randomInt(281474976710655)}`
237 if (existsSync(baseDirectory
) === true) {
238 rmSync(baseDirectory
, { recursive
: true })
240 mkdirSync(baseDirectory
, { recursive
: true })
241 for (let i
= 0; i
< n
; i
++) {
242 const filePath
= `${baseDirectory}/${i}`
243 writeFileSync(filePath
, i
.toString(), {
247 readFileSync(filePath
, 'utf8')
249 rmSync(baseDirectory
, { recursive
: true })
253 const executeTaskFunction
= data
=> {
254 switch (data
.function) {
255 case TaskFunctions
.jsonIntegerSerialization
:
256 return jsonIntegerSerialization(data
.taskSize
|| 1000)
257 case TaskFunctions
.fibonacci
:
258 return fibonacci(data
.taskSize
|| 1000)
259 case TaskFunctions
.factorial
:
260 return factorial(data
.taskSize
|| 1000)
261 case TaskFunctions
.readWriteFiles
:
262 return readWriteFiles(data
.taskSize
|| 1000)
264 throw new Error('Unknown task function')
271 generateRandomInteger
,
272 runPoolifierPoolBenchmark