@@ -28,45 +28,103 @@ function runBenchmark(
2828 benchmark : string ,
2929 benchmarkProjects : ReadonlyArray < BenchmarkProject > ,
3030) : void {
31- const results : Array < BenchmarkResult > = [ ] ;
31+ const memorySamples : Array < Array < number > > = [ ] ;
3232 for ( let i = 0 ; i < benchmarkProjects . length ; ++ i ) {
33- const { revision, projectPath } = benchmarkProjects [ i ] ;
34- const modulePath = path . join ( projectPath , benchmark ) ;
33+ const modulePath = path . join ( benchmarkProjects [ i ] . projectPath , benchmark ) ;
3534
3635 if ( i === 0 ) {
3736 console . log ( '\u23F1 ' + getBenchmarkName ( modulePath ) ) ;
3837 }
3938
4039 try {
41- const timingSamples = collectTimingSamples ( modulePath ) ;
42- const memorySamples = collectMemorySamples ( modulePath ) ;
43-
44- results . push ( computeStats ( revision , timingSamples , memorySamples ) ) ;
45- process . stdout . write ( ' ' + cyan ( i + 1 ) + ' tests completed.\u000D' ) ;
40+ memorySamples [ i ] = collectMemorySamples ( modulePath ) ;
41+ process . stdout . write (
42+ ' completed ' + cyan ( i + 1 ) + ' memory tests...\u000D' ,
43+ ) ;
4644 } catch ( error ) {
4745 const errorMessage =
4846 error instanceof Error ? error . message : String ( error ) ;
49- console . log ( ' ' + revision + ': ' + red ( errorMessage ) ) ;
47+ console . log (
48+ ' ' + benchmarkProjects [ i ] . revision + ': ' + red ( errorMessage ) ,
49+ ) ;
50+ return ;
5051 }
5152 }
53+ process . stdout . write ( '\n' ) ;
54+
55+ let timingSamples : Array < Array < number > > ;
56+ try {
57+ timingSamples = collectTimingSamples ( benchmark , benchmarkProjects ) ;
58+ } catch {
59+ console . log ( ' ' + red ( 'timing samples collection failed' ) ) ;
60+ return ;
61+ }
62+
63+ const results : Array < BenchmarkResult > = [ ] ;
64+ for ( let i = 0 ; i < benchmarkProjects . length ; ++ i ) {
65+ results . push (
66+ computeStats (
67+ benchmarkProjects [ i ] . revision ,
68+ timingSamples [ i ] ,
69+ memorySamples [ i ] ,
70+ ) ,
71+ ) ;
72+ }
73+
5274 console . log ( '\n' ) ;
5375
5476 printBenchmarkResults ( results ) ;
5577 console . log ( '' ) ;
5678}
5779
58- export function collectTimingSamples ( modulePath : string ) : Array < number > {
59- const samples : Array < number > = [ ] ;
80+ function collectTimingSamples (
81+ benchmark : string ,
82+ benchmarkProjects : ReadonlyArray < BenchmarkProject > ,
83+ ) : Array < Array < number > > {
84+ const sampleGroups = benchmarkProjects . map ( ( project ) => ( {
85+ revision : project . revision ,
86+ modulePath : path . join ( project . projectPath , benchmark ) ,
87+ samples : new Array < number > ( ) ,
88+ } ) ) ;
6089
6190 // If time permits, increase sample size to reduce the margin of error.
6291 const start = Date . now ( ) ;
63- while ( samples . length < minSamples || ( Date . now ( ) - start ) / 1e3 < maxTime ) {
64- const sample = sampleTimingModule ( modulePath ) ;
92+ let round = 0 ;
93+ while ( round < minSamples || ( Date . now ( ) - start ) / 1e3 < maxTime ) {
94+ for ( const sampleGroup of shuffled ( sampleGroups ) ) {
95+ try {
96+ const sample = sampleTimingModule ( sampleGroup . modulePath ) ;
6597
66- assert ( sample > 0 ) ;
67- samples . push ( sample ) ;
98+ assert ( sample > 0 ) ;
99+ sampleGroup . samples . push ( sample ) ;
100+ } catch ( error ) {
101+ const errorMessage =
102+ error instanceof Error ? error . message : String ( error ) ;
103+ console . log ( ' ' + sampleGroup . revision + ': ' + red ( errorMessage ) ) ;
104+ throw error ;
105+ }
106+ }
107+
108+ ++ round ;
109+ process . stdout . write (
110+ ' completed ' + cyan ( round ) + ' timing rounds...\u000D' ,
111+ ) ;
68112 }
69- return samples ;
113+ return sampleGroups . map ( ( { samples } ) => samples ) ;
114+ }
115+
116+ function shuffled < T > ( array : ReadonlyArray < T > ) : Array < T > {
117+ const shuffledArray = [ ...array ] ;
118+ // Fisher-Yates shuffle: walk backward and swap each slot with a random
119+ // earlier slot, including itself, to produce an unbiased permutation.
120+ for ( let index = shuffledArray . length - 1 ; index > 0 ; -- index ) {
121+ const randomIndex = Math . floor ( Math . random ( ) * ( index + 1 ) ) ;
122+ [ shuffledArray [ index ] , shuffledArray [ randomIndex ] ] = [
123+ shuffledArray [ randomIndex ] ,
124+ shuffledArray [ index ] ,
125+ ] ;
126+ }
127+ return shuffledArray ;
70128}
71129
72130export function collectMemorySamples ( modulePath : string ) : Array < number > {
0 commit comments