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 generateRandomInteger = (
177 max = Number.MAX_SAFE_INTEGER,
180 if (max < min || max < 0 || min < 0) {
181 throw new RangeError('Invalid interval')
183 max = Math.floor(max)
184 if (min != null && min !== 0) {
186 return Math.floor(Math.random() * (max - min + 1)) + min
188 return Math.floor(Math.random() * (max + 1))
191 const jsonIntegerSerialization = n => {
192 for (let i = 0; i < n; i++) {
202 * Intentionally inefficient implementation.
203 * @param {number} n - The number of fibonacci numbers to generate.
204 * @returns {number} - The nth fibonacci number.
206 const fibonacci = n => {
208 return fibonacci(n - 1) + fibonacci(n - 2)
212 * Intentionally inefficient implementation.
213 * @param {number} n - The number to calculate the factorial of.
214 * @returns {number} - The factorial of n.
216 const factorial = n => {
220 return factorial(n - 1) * n
223 const readWriteFiles = (
225 baseDirectory = `/tmp/poolifier-benchmarks/${crypto.randomInt(
229 if (fs.existsSync(baseDirectory) === true) {
230 fs.rmSync(baseDirectory, { recursive: true })
232 fs.mkdirSync(baseDirectory, { recursive: true })
233 for (let i = 0; i < n; i++) {
234 const filePath = `${baseDirectory}/${i}`
235 fs.writeFileSync(filePath, i.toString(), {
239 fs.readFileSync(filePath, 'utf8')
241 fs.rmSync(baseDirectory, { recursive: true })
245 export const executeTaskFunction = data => {
246 switch (data.function) {
247 case TaskFunctions.jsonIntegerSerialization:
248 return jsonIntegerSerialization(data.taskSize || 1000)
249 case TaskFunctions.fibonacci:
250 return fibonacci(data.taskSize || 1000)
251 case TaskFunctions.factorial:
252 return factorial(data.taskSize || 1000)
253 case TaskFunctions.readWriteFiles:
254 return readWriteFiles(data.taskSize || 1000)
256 throw new Error('Unknown task function')