|
1 | 1 | import assert from 'node:assert'; |
2 | | -import cp from 'node:child_process'; |
3 | | -import url from 'node:url'; |
4 | 2 |
|
5 | 3 | import { maxTime, minSamples } from './config.js'; |
6 | 4 | import { yellow } from './output.js'; |
7 | 5 | import type { BenchmarkSample } from './types.js'; |
| 6 | +import { sampleModule } from './workers.js'; |
| 7 | + |
| 8 | +export { sampleModule }; |
8 | 9 |
|
9 | 10 | export function collectSamples(modulePath: string): Array<BenchmarkSample> { |
10 | 11 | let numOfConsequentlyRejectedSamples = 0; |
@@ -35,72 +36,3 @@ export function collectSamples(modulePath: string): Array<BenchmarkSample> { |
35 | 36 | } |
36 | 37 | return samples; |
37 | 38 | } |
38 | | - |
39 | | -export function sampleModule(modulePath: string): BenchmarkSample { |
40 | | - // To support Windows we need to use URL instead of path |
41 | | - const moduleURL = url.pathToFileURL(modulePath); |
42 | | - |
43 | | - const sampleCode = ` |
44 | | - import fs from 'node:fs'; |
45 | | -
|
46 | | - import { benchmark } from '${moduleURL}'; |
47 | | -
|
48 | | - // warm up, it looks like 7 is a magic number to reliably trigger JIT |
49 | | - await benchmark.measure(); |
50 | | - await benchmark.measure(); |
51 | | - await benchmark.measure(); |
52 | | - await benchmark.measure(); |
53 | | - await benchmark.measure(); |
54 | | - await benchmark.measure(); |
55 | | - await benchmark.measure(); |
56 | | -
|
57 | | - const memBaseline = process.memoryUsage().heapUsed; |
58 | | -
|
59 | | - const resourcesStart = process.resourceUsage(); |
60 | | - const startTime = process.hrtime.bigint(); |
61 | | - for (let i = 0; i < benchmark.count; ++i) { |
62 | | - await benchmark.measure(); |
63 | | - } |
64 | | - const timeDiff = Number(process.hrtime.bigint() - startTime); |
65 | | - const resourcesEnd = process.resourceUsage(); |
66 | | -
|
67 | | - const result = { |
68 | | - name: benchmark.name, |
69 | | - clocked: timeDiff / benchmark.count, |
70 | | - memUsed: (process.memoryUsage().heapUsed - memBaseline) / benchmark.count, |
71 | | - involuntaryContextSwitches: |
72 | | - resourcesEnd.involuntaryContextSwitches - resourcesStart.involuntaryContextSwitches, |
73 | | - }; |
74 | | - fs.writeFileSync(3, JSON.stringify(result)); |
75 | | - `; |
76 | | - |
77 | | - const result = cp.spawnSync( |
78 | | - process.execPath, |
79 | | - [ |
80 | | - // V8 flags |
81 | | - '--predictable', |
82 | | - '--no-concurrent-sweeping', |
83 | | - '--no-minor-gc-task', |
84 | | - '--min-semi-space-size=1280', // 1.25GB |
85 | | - '--max-semi-space-size=1280', // 1.25GB |
86 | | - '--trace-gc', // no gc calls should happen during benchmark, so trace them |
87 | | - |
88 | | - // Node.js flags |
89 | | - '--input-type=module', |
90 | | - '--eval', |
91 | | - sampleCode, |
92 | | - ], |
93 | | - { |
94 | | - stdio: ['inherit', 'inherit', 'inherit', 'pipe'], |
95 | | - env: { NODE_ENV: 'production' }, |
96 | | - }, |
97 | | - ); |
98 | | - |
99 | | - if (result.status !== 0) { |
100 | | - throw new Error(`Benchmark failed with "${result.status}" status.`); |
101 | | - } |
102 | | - |
103 | | - const resultStr = result.output[3]?.toString(); |
104 | | - assert(resultStr != null); |
105 | | - return JSON.parse(resultStr); |
106 | | -} |
0 commit comments