1 import crypto from 'node:crypto'
2 import assert from 'node:assert'
3 import fs from 'node:fs'
4 import Benchmark from 'benchmark'
12 WorkerChoiceStrategies,
14 } from '../lib/index.mjs'
15 import { TaskFunctions } from './benchmarks-types.mjs'
17 export const buildPoolifierPool = (
26 case WorkerTypes.thread:
27 return new FixedThreadPool(
29 './benchmarks/internal/thread-worker.mjs',
32 case WorkerTypes.cluster:
33 return new FixedClusterPool(
35 './benchmarks/internal/cluster-worker.mjs',
40 case PoolTypes.dynamic:
42 case WorkerTypes.thread:
43 return new DynamicThreadPool(
44 Math.floor(poolSize / 2),
46 './benchmarks/internal/thread-worker.mjs',
49 case WorkerTypes.cluster:
50 return new DynamicClusterPool(
51 Math.floor(poolSize / 2),
53 './benchmarks/internal/cluster-worker.mjs',
61 export const runPoolifierPool = async (
63 { taskExecutions, workerData }
65 return await new Promise((resolve, reject) => {
67 for (let i = 1; i <= taskExecutions; i++) {
72 if (executions === taskExecutions) {
85 export const runPoolifierPoolBenchmark = async (
88 { taskExecutions, workerData }
90 return await new Promise((resolve, reject) => {
92 const suite = new Benchmark.Suite(name)
93 for (const workerChoiceStrategy of Object.values(
94 WorkerChoiceStrategies
96 for (const enableTasksQueue of [false, true]) {
97 if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
98 for (const measurement of [
103 `${name} with ${workerChoiceStrategy}, with ${measurement} and ${
104 enableTasksQueue ? 'with' : 'without'
107 pool.setWorkerChoiceStrategy(workerChoiceStrategy, {
110 pool.enableTasksQueue(enableTasksQueue)
112 pool.opts.workerChoiceStrategy,
116 pool.opts.enableTasksQueue,
120 pool.opts.workerChoiceStrategyOptions.measurement,
123 await runPoolifierPool(pool, {
132 `${name} with ${workerChoiceStrategy} and ${
133 enableTasksQueue ? 'with' : 'without'
136 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
137 pool.enableTasksQueue(enableTasksQueue)
139 pool.opts.workerChoiceStrategy,
142 assert.strictEqual(pool.opts.enableTasksQueue, enableTasksQueue)
143 await runPoolifierPool(pool, {
153 .on('cycle', event => {
154 console.info(event.target.toString())
156 .on('complete', async function () {
159 LIST_FORMATTER.format(this.filter('fastest').map('name'))
164 .run({ async: true })
171 export const LIST_FORMATTER = new Intl.ListFormat('en-US', {
176 export const executeAsyncFn = async fn => {
181 // eslint-disable-next-line n/no-process-exit
186 export const generateRandomInteger = (
187 max = Number.MAX_SAFE_INTEGER,
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/${crypto.randomInt(
239 if (fs.existsSync(baseDirectory) === true) {
240 fs.rmSync(baseDirectory, { recursive: true })
242 fs.mkdirSync(baseDirectory, { recursive: true })
243 for (let i = 0; i < n; i++) {
244 const filePath = `${baseDirectory}/${i}`
245 fs.writeFileSync(filePath, i.toString(), {
249 fs.readFileSync(filePath, 'utf8')
251 fs.rmSync(baseDirectory, { recursive: true })
255 export const executeTaskFunction = data => {
256 switch (data.function) {
257 case TaskFunctions.jsonIntegerSerialization:
258 return jsonIntegerSerialization(data.taskSize || 1000)
259 case TaskFunctions.fibonacci:
260 return fibonacci(data.taskSize || 1000)
261 case TaskFunctions.factorial:
262 return factorial(data.taskSize || 1000)
263 case TaskFunctions.readWriteFiles:
264 return readWriteFiles(data.taskSize || 1000)
266 throw new Error('Unknown task function')