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