refactor: convert to ESM benchmarks code
[poolifier.git] / benchmarks / benchmarks-utils.mjs
1 import crypto from 'crypto'
2 import fs from 'fs'
3 import {
4 DynamicClusterPool,
5 DynamicThreadPool,
6 FixedClusterPool,
7 FixedThreadPool
8 } from '../lib/index.mjs'
9 import { PoolTypes, WorkerFunctions, WorkerTypes } from './benchmarks-types.mjs'
10
11 async function runTest (pool, { taskExecutions, workerData }) {
12 return new Promise((resolve, reject) => {
13 let executions = 0
14 for (let i = 1; i <= taskExecutions; i++) {
15 pool
16 .execute(workerData)
17 .then(() => {
18 ++executions
19 if (executions === taskExecutions) {
20 return resolve({ ok: 1 })
21 }
22 return null
23 })
24 .catch(err => {
25 console.error(err)
26 return reject(err)
27 })
28 }
29 })
30 }
31
32 function generateRandomInteger (max = Number.MAX_SAFE_INTEGER, min = 0) {
33 if (max < min || max < 0 || min < 0) {
34 throw new RangeError('Invalid interval')
35 }
36 max = Math.floor(max)
37 if (min != null && min !== 0) {
38 min = Math.ceil(min)
39 return Math.floor(Math.random() * (max - min + 1)) + min
40 }
41 return Math.floor(Math.random() * (max + 1))
42 }
43
44 function jsonIntegerSerialization (n) {
45 for (let i = 0; i < n; i++) {
46 const o = {
47 a: i
48 }
49 JSON.stringify(o)
50 }
51 }
52
53 /**
54 * Intentionally inefficient implementation.
55 * @param {number} n - The number of fibonacci numbers to generate.
56 * @returns {number} - The nth fibonacci number.
57 */
58 function fibonacci (n) {
59 if (n <= 1) return 1
60 return fibonacci(n - 1) + fibonacci(n - 2)
61 }
62
63 /**
64 * Intentionally inefficient implementation.
65 * @param {number} n - The number to calculate the factorial of.
66 * @returns {number} - The factorial of n.
67 */
68 function factorial (n) {
69 if (n === 0) {
70 return 1
71 }
72 return factorial(n - 1) * n
73 }
74
75 function readWriteFiles (
76 n,
77 baseDirectory = `/tmp/poolifier-benchmarks/${crypto.randomInt(
78 281474976710655
79 )}`
80 ) {
81 if (fs.existsSync(baseDirectory) === true) {
82 fs.rmSync(baseDirectory, { recursive: true })
83 }
84 fs.mkdirSync(baseDirectory, { recursive: true })
85 for (let i = 0; i < n; i++) {
86 const filePath = `${baseDirectory}/${i}`
87 fs.writeFileSync(filePath, i.toString(), {
88 encoding: 'utf8',
89 flag: 'a'
90 })
91 fs.readFileSync(filePath, 'utf8')
92 }
93 fs.rmSync(baseDirectory, { recursive: true })
94 }
95
96 function executeWorkerFunction (data) {
97 switch (data.function) {
98 case WorkerFunctions.jsonIntegerSerialization:
99 return jsonIntegerSerialization(data.taskSize || 1000)
100 case WorkerFunctions.fibonacci:
101 return fibonacci(data.taskSize || 1000)
102 case WorkerFunctions.factorial:
103 return factorial(data.taskSize || 1000)
104 case WorkerFunctions.readWriteFiles:
105 return readWriteFiles(data.taskSize || 1000)
106 default:
107 throw new Error('Unknown worker function')
108 }
109 }
110
111 function buildPool (workerType, poolType, poolSize, poolOptions) {
112 switch (poolType) {
113 case PoolTypes.fixed:
114 switch (workerType) {
115 case WorkerTypes.thread:
116 return new FixedThreadPool(
117 poolSize,
118 './benchmarks/internal/thread-worker.mjs',
119 poolOptions
120 )
121 case WorkerTypes.cluster:
122 return new FixedClusterPool(
123 poolSize,
124 './benchmarks/internal/cluster-worker.mjs',
125 poolOptions
126 )
127 }
128 break
129 case PoolTypes.dynamic:
130 switch (workerType) {
131 case WorkerTypes.thread:
132 return new DynamicThreadPool(
133 poolSize / 2,
134 poolSize * 3,
135 './benchmarks/internal/thread-worker.mjs',
136 poolOptions
137 )
138 case WorkerTypes.cluster:
139 return new DynamicClusterPool(
140 poolSize / 2,
141 poolSize * 3,
142 './benchmarks/internal/cluster-worker.mjs',
143 poolOptions
144 )
145 }
146 break
147 }
148 }
149
150 export {
151 WorkerFunctions,
152 buildPool,
153 executeWorkerFunction,
154 generateRandomInteger,
155 readWriteFiles,
156 runTest
157 }