Commit | Line | Data |
---|---|---|
0804b9b4 | 1 | import { strictEqual } from 'node:assert' |
ce711c4a | 2 | import { env } from 'node:process' |
0804b9b4 JB |
3 | |
4 | import Benchmark from 'benchmark' | |
98f60ddd | 5 | import { bench, clear, group, run } from 'tatami-ng' |
0804b9b4 JB |
6 | |
7 | import { | |
8 | DynamicClusterPool, | |
9 | DynamicThreadPool, | |
10 | FixedClusterPool, | |
11 | FixedThreadPool, | |
12 | Measurements, | |
13 | PoolTypes, | |
14 | WorkerChoiceStrategies, | |
15 | WorkerTypes | |
16 | } from '../lib/index.mjs' | |
a6bef8d2 | 17 | import { executeTaskFunction } from './benchmarks-utils.cjs' |
0804b9b4 JB |
18 | |
19 | const buildPoolifierPool = (workerType, poolType, poolSize, poolOptions) => { | |
20 | switch (poolType) { | |
21 | case PoolTypes.fixed: | |
22 | switch (workerType) { | |
23 | case WorkerTypes.thread: | |
24 | return new FixedThreadPool( | |
25 | poolSize, | |
26 | './benchmarks/internal/thread-worker.mjs', | |
27 | poolOptions | |
28 | ) | |
29 | case WorkerTypes.cluster: | |
30 | return new FixedClusterPool( | |
31 | poolSize, | |
32 | './benchmarks/internal/cluster-worker.cjs', | |
33 | poolOptions | |
34 | ) | |
35 | } | |
36 | break | |
37 | case PoolTypes.dynamic: | |
38 | switch (workerType) { | |
39 | case WorkerTypes.thread: | |
40 | return new DynamicThreadPool( | |
41 | Math.floor(poolSize / 2), | |
42 | poolSize, | |
43 | './benchmarks/internal/thread-worker.mjs', | |
44 | poolOptions | |
45 | ) | |
46 | case WorkerTypes.cluster: | |
47 | return new DynamicClusterPool( | |
48 | Math.floor(poolSize / 2), | |
49 | poolSize, | |
50 | './benchmarks/internal/cluster-worker.cjs', | |
51 | poolOptions | |
52 | ) | |
53 | } | |
54 | break | |
55 | } | |
56 | } | |
57 | ||
58 | const runPoolifierPool = async (pool, { taskExecutions, workerData }) => { | |
59 | return await new Promise((resolve, reject) => { | |
60 | let executions = 0 | |
61 | for (let i = 1; i <= taskExecutions; i++) { | |
62 | pool | |
63 | .execute(workerData) | |
64 | .then(() => { | |
65 | ++executions | |
66 | if (executions === taskExecutions) { | |
67 | resolve({ ok: 1 }) | |
68 | } | |
69 | return undefined | |
70 | }) | |
71 | .catch(err => { | |
72 | console.error(err) | |
73 | reject(err) | |
74 | }) | |
75 | } | |
76 | }) | |
77 | } | |
78 | ||
79 | export const runPoolifierBenchmarkBenchmarkJs = async ( | |
6da2cd97 JB |
80 | name, |
81 | workerType, | |
82 | poolType, | |
83 | poolSize, | |
84 | poolOptions, | |
85 | { taskExecutions, workerData } | |
86 | ) => { | |
87 | return await new Promise((resolve, reject) => { | |
88 | const pool = buildPoolifierPool(workerType, poolType, poolSize, poolOptions) | |
89 | let workerChoiceStrategy | |
90 | let enableTasksQueue | |
91 | let workerChoiceStrategyOptions | |
92 | if (poolOptions != null) { | |
93 | ({ | |
94 | workerChoiceStrategy, | |
95 | enableTasksQueue, | |
96 | workerChoiceStrategyOptions | |
97 | } = poolOptions) | |
98 | } | |
99 | const measurement = workerChoiceStrategyOptions?.measurement | |
100 | new Benchmark( | |
101 | `${name} with ${workerChoiceStrategy ?? pool.opts.workerChoiceStrategy}${ | |
102 | measurement != null ? `, with ${measurement}` : '' | |
103 | } and ${enableTasksQueue ? 'with' : 'without'} tasks queue`, | |
104 | async () => { | |
105 | await runPoolifierPool(pool, { | |
106 | taskExecutions, | |
107 | workerData | |
108 | }) | |
109 | }, | |
110 | { | |
111 | onStart: () => { | |
112 | if (workerChoiceStrategy != null) { | |
113 | strictEqual(pool.opts.workerChoiceStrategy, workerChoiceStrategy) | |
114 | } | |
115 | if (enableTasksQueue != null) { | |
116 | strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) | |
117 | } | |
118 | if (measurement != null) { | |
119 | strictEqual( | |
120 | pool.opts.workerChoiceStrategyOptions.measurement, | |
121 | measurement | |
122 | ) | |
123 | } | |
124 | }, | |
125 | onComplete: event => { | |
126 | console.info(event.target.toString()) | |
127 | if (pool.started && !pool.destroying) { | |
128 | pool.destroy().then(resolve).catch(reject) | |
129 | } else { | |
130 | resolve() | |
131 | } | |
132 | }, | |
133 | onError: event => { | |
134 | if (pool.started && !pool.destroying) { | |
135 | pool | |
136 | .destroy() | |
137 | .then(() => { | |
138 | return reject(event.target.error) | |
139 | }) | |
140 | .catch(() => {}) | |
141 | } else { | |
142 | reject(event.target.error) | |
143 | } | |
144 | } | |
145 | } | |
cc8689da | 146 | ).run({ async: true }) |
6da2cd97 JB |
147 | }) |
148 | } | |
149 | ||
150 | export const runPoolifierBenchmarkBenchmarkJsSuite = async ( | |
0804b9b4 JB |
151 | name, |
152 | workerType, | |
153 | poolType, | |
154 | poolSize, | |
155 | { taskExecutions, workerData } | |
156 | ) => { | |
157 | return await new Promise((resolve, reject) => { | |
6aec0be3 | 158 | const pool = buildPoolifierPool(workerType, poolType, poolSize) |
47ab5d23 JB |
159 | const suite = new Benchmark.Suite(name, { |
160 | onComplete: () => { | |
161 | if (pool.started && !pool.destroying) { | |
162 | pool.destroy().then(resolve).catch(reject) | |
163 | } else { | |
164 | resolve() | |
fe7488e9 | 165 | } |
47ab5d23 JB |
166 | }, |
167 | onCycle: event => { | |
168 | console.info(event.target.toString()) | |
169 | }, | |
170 | onError: event => { | |
171 | if (pool.started && !pool.destroying) { | |
172 | pool | |
173 | .destroy() | |
174 | .then(() => { | |
175 | return reject(event.target.error) | |
176 | }) | |
177 | .catch(() => {}) | |
178 | } else { | |
179 | reject(event.target.error) | |
180 | } | |
181 | } | |
182 | }) | |
183 | for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) { | |
184 | for (const enableTasksQueue of [false, true]) { | |
185 | if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) { | |
186 | for (const measurement of [Measurements.runTime, Measurements.elu]) { | |
0804b9b4 | 187 | suite.add( |
6da2cd97 | 188 | `${name} with ${workerChoiceStrategy}, with ${measurement} and ${ |
0804b9b4 JB |
189 | enableTasksQueue ? 'with' : 'without' |
190 | } tasks queue`, | |
191 | async () => { | |
0804b9b4 JB |
192 | await runPoolifierPool(pool, { |
193 | taskExecutions, | |
194 | workerData | |
195 | }) | |
083213c6 JB |
196 | }, |
197 | { | |
198 | onStart: () => { | |
47ab5d23 JB |
199 | pool.setWorkerChoiceStrategy(workerChoiceStrategy, { |
200 | measurement | |
201 | }) | |
083213c6 JB |
202 | pool.enableTasksQueue(enableTasksQueue) |
203 | strictEqual( | |
204 | pool.opts.workerChoiceStrategy, | |
205 | workerChoiceStrategy | |
206 | ) | |
207 | strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) | |
47ab5d23 JB |
208 | strictEqual( |
209 | pool.opts.workerChoiceStrategyOptions.measurement, | |
210 | measurement | |
211 | ) | |
083213c6 | 212 | } |
0804b9b4 JB |
213 | } |
214 | ) | |
215 | } | |
47ab5d23 JB |
216 | } else { |
217 | suite.add( | |
218 | `${name} with ${workerChoiceStrategy} and ${ | |
219 | enableTasksQueue ? 'with' : 'without' | |
220 | } tasks queue`, | |
221 | async () => { | |
222 | await runPoolifierPool(pool, { | |
223 | taskExecutions, | |
224 | workerData | |
225 | }) | |
226 | }, | |
227 | { | |
228 | onStart: () => { | |
229 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) | |
230 | pool.enableTasksQueue(enableTasksQueue) | |
231 | strictEqual( | |
232 | pool.opts.workerChoiceStrategy, | |
233 | workerChoiceStrategy | |
234 | ) | |
235 | strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) | |
236 | } | |
237 | } | |
238 | ) | |
0804b9b4 JB |
239 | } |
240 | } | |
0804b9b4 | 241 | } |
47ab5d23 JB |
242 | suite |
243 | .on('complete', function () { | |
244 | console.info( | |
245 | 'Fastest is ' + | |
246 | LIST_FORMATTER.format(this.filter('fastest').map('name')) | |
247 | ) | |
248 | }) | |
249 | .run({ async: true }) | |
0804b9b4 JB |
250 | }) |
251 | } | |
252 | ||
b5ca7c94 | 253 | export const runPoolifierBenchmarkTatamiNg = async ( |
0804b9b4 JB |
254 | name, |
255 | workerType, | |
256 | poolType, | |
257 | poolSize, | |
258 | { taskExecutions, workerData } | |
259 | ) => { | |
260 | try { | |
261 | const pool = buildPoolifierPool(workerType, poolType, poolSize) | |
262 | for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) { | |
263 | for (const enableTasksQueue of [false, true]) { | |
264 | if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) { | |
265 | for (const measurement of [Measurements.runTime, Measurements.elu]) { | |
266 | group(name, () => { | |
267 | bench( | |
268 | `${name} with ${workerChoiceStrategy}, with ${measurement} and ${ | |
269 | enableTasksQueue ? 'with' : 'without' | |
270 | } tasks queue`, | |
271 | async () => { | |
0804b9b4 JB |
272 | await runPoolifierPool(pool, { |
273 | taskExecutions, | |
274 | workerData | |
275 | }) | |
2baf75cf JB |
276 | }, |
277 | { | |
278 | before: () => { | |
279 | pool.setWorkerChoiceStrategy(workerChoiceStrategy, { | |
280 | measurement | |
281 | }) | |
282 | pool.enableTasksQueue(enableTasksQueue) | |
283 | strictEqual( | |
284 | pool.opts.workerChoiceStrategy, | |
285 | workerChoiceStrategy | |
286 | ) | |
287 | strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) | |
288 | strictEqual( | |
289 | pool.opts.workerChoiceStrategyOptions.measurement, | |
290 | measurement | |
291 | ) | |
292 | } | |
0804b9b4 JB |
293 | } |
294 | ) | |
295 | }) | |
296 | } | |
297 | } else { | |
298 | group(name, () => { | |
299 | bench( | |
300 | `${name} with ${workerChoiceStrategy} and ${ | |
301 | enableTasksQueue ? 'with' : 'without' | |
302 | } tasks queue`, | |
303 | async () => { | |
0804b9b4 JB |
304 | await runPoolifierPool(pool, { |
305 | taskExecutions, | |
306 | workerData | |
307 | }) | |
2baf75cf JB |
308 | }, |
309 | { | |
310 | before: () => { | |
311 | pool.setWorkerChoiceStrategy(workerChoiceStrategy) | |
312 | pool.enableTasksQueue(enableTasksQueue) | |
313 | strictEqual( | |
314 | pool.opts.workerChoiceStrategy, | |
315 | workerChoiceStrategy | |
316 | ) | |
317 | strictEqual(pool.opts.enableTasksQueue, enableTasksQueue) | |
318 | } | |
0804b9b4 JB |
319 | } |
320 | ) | |
321 | }) | |
322 | } | |
323 | } | |
324 | } | |
ce711c4a JB |
325 | await run({ |
326 | json: env.CI != null ? 'bmf' : false | |
327 | }) | |
16534b42 | 328 | clear() |
2baf75cf | 329 | await pool.destroy() |
0804b9b4 JB |
330 | } catch (error) { |
331 | console.error(error) | |
332 | } | |
333 | } | |
334 | ||
335 | const LIST_FORMATTER = new Intl.ListFormat('en-US', { | |
336 | style: 'long', | |
337 | type: 'conjunction' | |
338 | }) | |
a6bef8d2 JB |
339 | |
340 | export { executeTaskFunction } |