Commit | Line | Data |
---|---|---|
d5fdc57b JB |
1 | import crypto from 'node:crypto' |
2 | import fs from 'node:fs' | |
8f810074 | 3 | import { |
cdace0e5 JB |
4 | DynamicClusterPool, |
5 | DynamicThreadPool, | |
6 | FixedClusterPool, | |
d9d8c14e JB |
7 | FixedThreadPool, |
8 | PoolTypes, | |
9 | WorkerTypes | |
8f810074 | 10 | } from '../lib/index.mjs' |
dbca3be9 | 11 | import { TaskFunctions } from './benchmarks-types.mjs' |
2d2e32c2 | 12 | |
479ba9f6 JB |
13 | export 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 | ||
57 | export 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 |
81 | export const LIST_FORMATTER = new Intl.ListFormat('en-US', { |
82 | style: 'long', | |
83 | type: 'conjunction' | |
84 | }) | |
85 | ||
479ba9f6 JB |
86 | export 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 |
96 | export 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 | 111 | const 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 | 126 | const 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 | 136 | const 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 | 143 | const 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 | 165 | export 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 | } |