test: refine branches coverage
[poolifier.git] / benchmarks / benchmarks-utils.mjs
CommitLineData
d5fdc57b
JB
1import crypto from 'node:crypto'
2import fs from 'node:fs'
8f810074 3import {
cdace0e5
JB
4 DynamicClusterPool,
5 DynamicThreadPool,
6 FixedClusterPool,
d9d8c14e
JB
7 FixedThreadPool,
8 PoolTypes,
9 WorkerTypes
8f810074 10} from '../lib/index.mjs'
dbca3be9 11import { TaskFunctions } from './benchmarks-types.mjs'
2d2e32c2 12
479ba9f6
JB
13export const buildPoolifierPool = (
14 workerType,
15 poolType,
16 poolSize,
17 poolOptions
18) => {
19 switch (poolType) {
20 case PoolTypes.fixed:
21 switch (workerType) {
22 case WorkerTypes.thread:
23 return new FixedThreadPool(
24 poolSize,
25 './benchmarks/internal/thread-worker.mjs',
26 poolOptions
27 )
28 case WorkerTypes.cluster:
29 return new FixedClusterPool(
30 poolSize,
31 './benchmarks/internal/cluster-worker.mjs',
32 poolOptions
33 )
34 }
35 break
36 case PoolTypes.dynamic:
37 switch (workerType) {
38 case WorkerTypes.thread:
39 return new DynamicThreadPool(
40 Math.floor(poolSize / 2),
41 poolSize,
42 './benchmarks/internal/thread-worker.mjs',
43 poolOptions
44 )
45 case WorkerTypes.cluster:
46 return new DynamicClusterPool(
47 Math.floor(poolSize / 2),
48 poolSize,
49 './benchmarks/internal/cluster-worker.mjs',
50 poolOptions
51 )
52 }
53 break
54 }
55}
56
57export const runPoolifierTest = async (
58 pool,
59 { taskExecutions, workerData }
60) => {
ff5e76e1
JB
61 return new Promise((resolve, reject) => {
62 let executions = 0
cdace0e5 63 for (let i = 1; i <= taskExecutions; i++) {
ff5e76e1
JB
64 pool
65 .execute(workerData)
fe2f6f84 66 .then(() => {
0762fbb1 67 ++executions
cdace0e5 68 if (executions === taskExecutions) {
ca6c7d70 69 return resolve({ ok: 1 })
ff5e76e1
JB
70 }
71 return null
72 })
041dc05b 73 .catch(err => {
23ff945a
JB
74 console.error(err)
75 return reject(err)
76 })
ff5e76e1
JB
77 }
78 })
79}
80
f1c674cd
JB
81export const LIST_FORMATTER = new Intl.ListFormat('en-US', {
82 style: 'long',
83 type: 'conjunction'
84})
85
479ba9f6
JB
86export const executeAsyncFn = async fn => {
87 try {
88 await fn()
89 } catch (e) {
90 console.error(e)
91 // eslint-disable-next-line n/no-process-exit
92 process.exit(1)
93 }
94}
95
bac873bd
JB
96export const generateRandomInteger = (
97 max = Number.MAX_SAFE_INTEGER,
98 min = 0
99) => {
548140e6 100 if (max < min || max < 0 || min < 0) {
4af5c11a
JB
101 throw new RangeError('Invalid interval')
102 }
c2d7d79b 103 max = Math.floor(max)
4af5c11a 104 if (min != null && min !== 0) {
c2d7d79b 105 min = Math.ceil(min)
872585ea 106 return Math.floor(Math.random() * (max - min + 1)) + min
74750c7f 107 }
872585ea 108 return Math.floor(Math.random() * (max + 1))
74750c7f
JB
109}
110
041dc05b 111const jsonIntegerSerialization = n => {
cdace0e5
JB
112 for (let i = 0; i < n; i++) {
113 const o = {
114 a: i
115 }
116 JSON.stringify(o)
117 }
30b963d4 118 return { ok: 1 }
cdace0e5
JB
119}
120
bdacc2d2
JB
121/**
122 * Intentionally inefficient implementation.
7d82d90e
JB
123 * @param {number} n - The number of fibonacci numbers to generate.
124 * @returns {number} - The nth fibonacci number.
bdacc2d2 125 */
041dc05b 126const fibonacci = n => {
024daf59 127 if (n <= 1) return n
bdacc2d2
JB
128 return fibonacci(n - 1) + fibonacci(n - 2)
129}
130
7d82d90e
JB
131/**
132 * Intentionally inefficient implementation.
7d82d90e
JB
133 * @param {number} n - The number to calculate the factorial of.
134 * @returns {number} - The factorial of n.
135 */
041dc05b 136const factorial = n => {
7d82d90e
JB
137 if (n === 0) {
138 return 1
7d82d90e 139 }
965415bb 140 return factorial(n - 1) * n
7d82d90e
JB
141}
142
bac873bd 143const readWriteFiles = (
670734fc
JB
144 n,
145 baseDirectory = `/tmp/poolifier-benchmarks/${crypto.randomInt(
146 281474976710655
147 )}`
bac873bd 148) => {
670734fc
JB
149 if (fs.existsSync(baseDirectory) === true) {
150 fs.rmSync(baseDirectory, { recursive: true })
cdace0e5 151 }
670734fc 152 fs.mkdirSync(baseDirectory, { recursive: true })
cdace0e5
JB
153 for (let i = 0; i < n; i++) {
154 const filePath = `${baseDirectory}/${i}`
155 fs.writeFileSync(filePath, i.toString(), {
156 encoding: 'utf8',
157 flag: 'a'
158 })
159 fs.readFileSync(filePath, 'utf8')
160 }
670734fc 161 fs.rmSync(baseDirectory, { recursive: true })
30b963d4 162 return { ok: 1 }
cdace0e5
JB
163}
164
041dc05b 165export const executeTaskFunction = data => {
2d2e32c2 166 switch (data.function) {
dbca3be9 167 case TaskFunctions.jsonIntegerSerialization:
d1a9aa41 168 return jsonIntegerSerialization(data.taskSize || 1000)
dbca3be9 169 case TaskFunctions.fibonacci:
d1a9aa41 170 return fibonacci(data.taskSize || 1000)
dbca3be9 171 case TaskFunctions.factorial:
d1a9aa41 172 return factorial(data.taskSize || 1000)
dbca3be9 173 case TaskFunctions.readWriteFiles:
cdace0e5 174 return readWriteFiles(data.taskSize || 1000)
2d2e32c2 175 default:
dbca3be9 176 throw new Error('Unknown task function')
2d2e32c2
JB
177 }
178}