@@ -12,13 +12,13 @@ const maxTime = 5;
1212// The minimum sample size required to perform statistical analysis.
1313const minSamples = 5 ;
1414
15- async function runBenchmarks ( ) {
15+ function runBenchmarks ( ) {
1616 // Get the revisions and make things happen!
1717 const { benchmarks, revisions } = getArguments ( process . argv . slice ( 2 ) ) ;
1818 const benchmarkProjects = prepareBenchmarkProjects ( revisions ) ;
1919
2020 for ( const benchmark of benchmarks ) {
21- await runBenchmark ( benchmark , benchmarkProjects ) ;
21+ runBenchmark ( benchmark , benchmarkProjects ) ;
2222 }
2323}
2424
@@ -113,14 +113,14 @@ function prepareBenchmarkProjects(
113113 }
114114}
115115
116- async function collectSamples ( modulePath : string ) {
116+ function collectSamples ( modulePath : string ) {
117117 let numOfConsequentlyRejectedSamples = 0 ;
118118 const samples = [ ] ;
119119
120120 // If time permits, increase sample size to reduce the margin of error.
121121 const start = Date . now ( ) ;
122122 while ( samples . length < minSamples || ( Date . now ( ) - start ) / 1e3 < maxTime ) {
123- const sample = await sampleModule ( modulePath ) ;
123+ const sample = sampleModule ( modulePath ) ;
124124
125125 if ( sample . involuntaryContextSwitches > 0 ) {
126126 numOfConsequentlyRejectedSamples ++ ;
@@ -278,7 +278,7 @@ function maxBy<T>(array: ReadonlyArray<T>, fn: (obj: T) => number) {
278278}
279279
280280// Prepare all revisions and run benchmarks matching a pattern against them.
281- async function runBenchmark (
281+ function runBenchmark (
282282 benchmark : string ,
283283 benchmarkProjects : ReadonlyArray < BenchmarkProject > ,
284284) {
@@ -288,17 +288,17 @@ async function runBenchmark(
288288 const modulePath = path . join ( projectPath , benchmark ) ;
289289
290290 if ( i === 0 ) {
291- const { name } = await sampleModule ( modulePath ) ;
291+ const { name } = sampleModule ( modulePath ) ;
292292 console . log ( '⏱ ' + name ) ;
293293 }
294294
295295 try {
296- const samples = await collectSamples ( modulePath ) ;
296+ const samples = collectSamples ( modulePath ) ;
297297
298298 results . push ( computeStats ( revision , samples ) ) ;
299299 process . stdout . write ( ' ' + cyan ( i + 1 ) + ' tests completed.\u000D' ) ;
300300 } catch ( error ) {
301- console . log ( ' ' + revision + ': ' + red ( String ( error ) ) ) ;
301+ console . log ( ' ' + revision + ': ' + red ( error . message ) ) ;
302302 }
303303 }
304304 console . log ( '\n' ) ;
@@ -372,11 +372,9 @@ interface BenchmarkSample {
372372 involuntaryContextSwitches : number ;
373373}
374374
375- function sampleModule ( modulePath : string ) : Promise < BenchmarkSample > {
375+ function sampleModule ( modulePath : string ) : BenchmarkSample {
376376 const sampleCode = `
377- import assert from 'node:assert';
378-
379- assert(process.send);
377+ import fs from 'node:fs';
380378
381379 import { benchmark } from '${ modulePath } ';
382380
@@ -399,53 +397,45 @@ function sampleModule(modulePath: string): Promise<BenchmarkSample> {
399397 const timeDiff = Number(process.hrtime.bigint() - startTime);
400398 const resourcesEnd = process.resourceUsage();
401399
402- process.send( {
400+ const result = {
403401 name: benchmark.name,
404402 clocked: timeDiff / benchmark.count,
405403 memUsed: (process.memoryUsage().heapUsed - memBaseline) / benchmark.count,
406404 involuntaryContextSwitches:
407405 resourcesEnd.involuntaryContextSwitches - resourcesStart.involuntaryContextSwitches,
408- });
406+ };
407+ fs.writeFileSync(3, JSON.stringify(result));
409408 ` ;
410409
411- return new Promise ( ( resolve , reject ) => {
412- const child = cp . spawn (
413- process . execPath ,
414- [
415- // V8 flags
416- '--predictable' ,
417- '--no-concurrent-sweeping' ,
418- '--no-scavenge-task' ,
419- '--min-semi-space-size=1024' , // 1GB
420- '--max-semi-space-size=1024' , // 1GB
421- '--trace-gc' , // no gc calls should happen during benchmark, so trace them
422-
423- // Node.js flags
424- '--input-type=module' ,
425- '--eval' ,
426- sampleCode ,
427- ] ,
428- {
429- stdio : [ 'inherit' , 'inherit' , 'inherit' , 'ipc' ] ,
430- env : { NODE_ENV : 'production' } ,
431- } ,
432- ) ;
410+ const result = cp . spawnSync (
411+ process . execPath ,
412+ [
413+ // V8 flags
414+ '--predictable' ,
415+ '--no-concurrent-sweeping' ,
416+ '--no-scavenge-task' ,
417+ '--min-semi-space-size=1024' , // 1GB
418+ '--max-semi-space-size=1024' , // 1GB
419+ '--trace-gc' , // no gc calls should happen during benchmark, so trace them
420+
421+ // Node.js flags
422+ '--input-type=module' ,
423+ '--eval' ,
424+ sampleCode ,
425+ ] ,
426+ {
427+ stdio : [ 'inherit' , 'inherit' , 'inherit' , 'pipe' ] ,
428+ env : { NODE_ENV : 'production' } ,
429+ } ,
430+ ) ;
433431
434- let message : any ;
435- let error : any ;
432+ if ( result . status !== 0 ) {
433+ throw new Error ( `Benchmark failed with "${ result . status } " status.` ) ;
434+ }
436435
437- child . on ( 'message' , ( msg ) => ( message = msg ) ) ;
438- child . on ( 'error' , ( e ) => ( error = e ) ) ;
439- child . on ( 'close' , ( ) => {
440- if ( message ) {
441- return resolve ( message ) ;
442- }
443- reject ( error || new Error ( 'Spawn process closed without error' ) ) ;
444- } ) ;
445- } ) ;
436+ const resultStr = result . output [ 3 ] ?. toString ( ) ;
437+ assert ( resultStr != null ) ;
438+ return JSON . parse ( resultStr ) ;
446439}
447440
448- runBenchmarks ( ) . catch ( ( error ) => {
449- console . error ( error ) ;
450- process . exit ( 1 ) ;
451- } ) ;
441+ runBenchmarks ( ) ;
0 commit comments