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