1
- import { initCore , measurement , optimizeFunctionSync } from "@codspeed/core" ;
1
+ import {
2
+ initCore ,
3
+ measurement ,
4
+ optimizeFunction ,
5
+ optimizeFunctionSync ,
6
+ } from "@codspeed/core" ;
2
7
import Benchmark from "benchmark" ;
3
- import { findUpSync , Options } from "find-up" ;
8
+ import { findUpSync , Options as FindupOptions } from "find-up" ;
4
9
import path , { dirname } from "path" ;
5
10
import { get as getStackTrace } from "stack-trace" ;
6
11
7
12
declare const __VERSION__ : string ;
8
13
9
- export function withCodSpeed ( suite : Benchmark ) : Benchmark ;
10
- export function withCodSpeed ( suite : Benchmark . Suite ) : Benchmark . Suite ;
14
+ interface WithCodSpeedBenchmark
15
+ extends Omit <
16
+ Benchmark ,
17
+ "run" | "abort" | "clone" | "compare" | "emit" | "off" | "on" | "reset"
18
+ > {
19
+ abort ( ) : WithCodSpeedBenchmark ;
20
+ clone ( options : Benchmark . Options ) : WithCodSpeedBenchmark ;
21
+ compare ( benchmark : Benchmark ) : number ;
22
+ off (
23
+ type ?: string ,
24
+ listener ?: CallableFunction
25
+ ) : Benchmark | Promise < Benchmark > ;
26
+ off ( types : string [ ] ) : WithCodSpeedBenchmark ;
27
+ on ( type ?: string , listener ?: CallableFunction ) : WithCodSpeedBenchmark ;
28
+ on ( types : string [ ] ) : WithCodSpeedBenchmark ;
29
+ reset ( ) : WithCodSpeedBenchmark ;
30
+ // Makes run an async function
31
+ run ( options ?: Benchmark . Options ) : Benchmark | Promise < Benchmark > ;
32
+ }
33
+
34
+ interface WithCodSpeedSuite
35
+ extends Omit <
36
+ Benchmark . Suite ,
37
+ | "run"
38
+ | "abort"
39
+ | "clone"
40
+ | "compare"
41
+ | "emit"
42
+ | "off"
43
+ | "on"
44
+ | "reset"
45
+ | "add"
46
+ | "filter"
47
+ | "each"
48
+ | "forEach"
49
+ > {
50
+ abort ( ) : WithCodSpeedSuite ;
51
+ add (
52
+ name : string ,
53
+ fn : CallableFunction | string ,
54
+ options ?: Benchmark . Options
55
+ ) : WithCodSpeedSuite ;
56
+ add (
57
+ fn : CallableFunction | string ,
58
+ options ?: Benchmark . Options
59
+ ) : WithCodSpeedSuite ;
60
+ add ( name : string , options ?: Benchmark . Options ) : WithCodSpeedSuite ;
61
+ add ( options : Benchmark . Options ) : WithCodSpeedSuite ;
62
+ clone ( options : Benchmark . Options ) : WithCodSpeedSuite ;
63
+ filter ( callback : CallableFunction | string ) : WithCodSpeedSuite ;
64
+ off ( type ?: string , callback ?: CallableFunction ) : WithCodSpeedSuite ;
65
+ off ( types : string [ ] ) : WithCodSpeedSuite ;
66
+ on ( type ?: string , callback ?: CallableFunction ) : WithCodSpeedSuite ;
67
+ on ( types : string [ ] ) : WithCodSpeedSuite ;
68
+ reset ( ) : WithCodSpeedSuite ;
69
+ each ( callback : CallableFunction ) : WithCodSpeedSuite ;
70
+ forEach ( callback : CallableFunction ) : WithCodSpeedSuite ;
71
+
72
+ run ( options ?: Benchmark . Options ) : Benchmark . Suite | Promise < Benchmark . Suite > ;
73
+ }
74
+
75
+ export function withCodSpeed ( suite : Benchmark ) : WithCodSpeedBenchmark ;
76
+ export function withCodSpeed ( suite : Benchmark . Suite ) : WithCodSpeedSuite ;
11
77
export function withCodSpeed ( item : unknown ) : unknown {
12
78
if ( ( item as { length ?: number } ) . length === undefined ) {
13
79
return withCodSpeedBenchmark ( item as Benchmark ) ;
@@ -16,7 +82,7 @@ export function withCodSpeed(item: unknown): unknown {
16
82
}
17
83
}
18
84
19
- function withCodSpeedBenchmark ( bench : Benchmark ) : Benchmark {
85
+ function withCodSpeedBenchmark ( bench : Benchmark ) : WithCodSpeedBenchmark {
20
86
if ( ! measurement . isInstrumented ( ) ) {
21
87
const rawRun = bench . run ;
22
88
bench . run = ( options ?: Benchmark . Options ) => {
@@ -27,27 +93,22 @@ function withCodSpeedBenchmark(bench: Benchmark): Benchmark {
27
93
} ;
28
94
return bench ;
29
95
}
30
- initCore ( ) ;
31
96
const callingFile = getCallingFile ( ) ;
32
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
33
- bench . run = function ( options ?: Benchmark . Options ) : Benchmark {
34
- console . log (
35
- `[CodSpeed] running with @codspeed/benchmark.js v${ __VERSION__ } `
36
- ) ;
37
- const uri = callingFile + "::" + ( bench . name ?? "unknown" ) ;
38
- const fn = bench . fn as CallableFunction ;
39
- optimizeFunctionSync ( fn ) ;
40
- measurement . startInstrumentation ( ) ;
41
- fn ( ) ;
42
- measurement . stopInstrumentation ( uri ) ;
43
- console . log ( ` ✔ Measured ${ uri } ` ) ;
44
- console . log ( "[CodSpeed] Done running 1 bench." ) ;
97
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/ban-ts-comment
98
+ // @ts -ignore
99
+ bench . run = async function ( options ?: Benchmark . Options ) : Promise < Benchmark > {
100
+ await runBenchmarks ( {
101
+ benches : [ bench as unknown as BenchmarkWithOptions ] ,
102
+ baseUri : callingFile ,
103
+ benchmarkCompletedListeners : bench . listeners ( "complete" ) ,
104
+ options,
105
+ } ) ;
45
106
return bench ;
46
107
} ;
47
108
return bench ;
48
109
}
49
110
50
- function withCodSpeedSuite ( suite : Benchmark . Suite ) : Benchmark . Suite {
111
+ function withCodSpeedSuite ( suite : Benchmark . Suite ) : WithCodSpeedSuite {
51
112
if ( ! measurement . isInstrumented ( ) ) {
52
113
const rawRun = suite . run ;
53
114
suite . run = ( options ?: Benchmark . Options ) => {
@@ -56,35 +117,82 @@ function withCodSpeedSuite(suite: Benchmark.Suite): Benchmark.Suite {
56
117
) ;
57
118
return rawRun . bind ( suite ) ( options ) ;
58
119
} ;
59
- return suite ;
120
+ return suite as WithCodSpeedSuite ;
60
121
}
61
- initCore ( ) ;
62
122
const callingFile = getCallingFile ( ) ;
63
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
- suite . run = function ( options ?: Benchmark . Options ) : Benchmark . Suite {
65
- console . log (
66
- `[CodSpeed] running with @codspeed/benchmark.js v ${ __VERSION__ } `
67
- ) ;
123
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/ban-ts-comment
124
+ // @ts -ignore
125
+ suite . run = async function (
126
+ options ?: Benchmark . Options
127
+ ) : Promise < Benchmark . Suite > {
68
128
const suiteName = suite . name ;
69
- const benches = this as unknown as Benchmark [ ] ;
129
+ const benches = this as unknown as BenchmarkWithOptions [ ] ;
70
130
let baseUri = callingFile ;
71
131
if ( suiteName !== undefined ) {
72
132
baseUri += `::${ suiteName } ` ;
73
133
}
74
- for ( let i = 0 ; i < benches . length ; i ++ ) {
75
- const bench = benches [ i ] ;
76
- const uri = baseUri + "::" + ( bench . name ?? `unknown_${ i } ` ) ;
77
- const fn = bench . fn as CallableFunction ;
78
- optimizeFunctionSync ( fn ) ;
134
+ await runBenchmarks ( {
135
+ benches,
136
+ baseUri,
137
+ benchmarkCompletedListeners : suite . listeners ( "complete" ) ,
138
+ options,
139
+ } ) ;
140
+ return suite ;
141
+ } ;
142
+ return suite as WithCodSpeedSuite ;
143
+ }
144
+
145
+ type BenchmarkWithOptions = Benchmark & { options : Benchmark . Options } ;
146
+
147
+ interface RunBenchmarksOptions {
148
+ benches : BenchmarkWithOptions [ ] ;
149
+ baseUri : string ;
150
+ benchmarkCompletedListeners : CallableFunction [ ] ;
151
+ options ?: Benchmark . Options ;
152
+ }
153
+
154
+ async function runBenchmarks ( {
155
+ benches,
156
+ baseUri,
157
+ benchmarkCompletedListeners,
158
+ options,
159
+ } : RunBenchmarksOptions ) : Promise < void > {
160
+ console . log ( `[CodSpeed] running with @codspeed/benchmark.js v${ __VERSION__ } ` ) ;
161
+ initCore ( ) ;
162
+ for ( let i = 0 ; i < benches . length ; i ++ ) {
163
+ const bench = benches [ i ] ;
164
+ const uri = baseUri + "::" + ( bench . name ?? `unknown_${ i } ` ) ;
165
+ const isAsync =
166
+ bench . options . async || bench . options . defer || options ?. async ;
167
+ let benchPayload ;
168
+ if ( bench . options . defer ) {
169
+ benchPayload = ( ) => {
170
+ return new Promise ( ( resolve , reject ) => {
171
+ ( bench . fn as CallableFunction ) ( { resolve, reject } ) ;
172
+ } ) ;
173
+ } ;
174
+ } else if ( bench . options . async ) {
175
+ benchPayload = async ( ) => {
176
+ await ( bench . fn as CallableFunction ) ( ) ;
177
+ } ;
178
+ } else {
179
+ benchPayload = bench . fn as CallableFunction ;
180
+ }
181
+ if ( isAsync ) {
182
+ await optimizeFunction ( benchPayload ) ;
79
183
measurement . startInstrumentation ( ) ;
80
- ( bench . fn as CallableFunction ) ( ) ;
184
+ await benchPayload ( ) ;
185
+ measurement . stopInstrumentation ( uri ) ;
186
+ } else {
187
+ optimizeFunctionSync ( benchPayload ) ;
188
+ measurement . startInstrumentation ( ) ;
189
+ benchPayload ( ) ;
81
190
measurement . stopInstrumentation ( uri ) ;
82
- console . log ( ` ✔ Measured ${ uri } ` ) ;
83
191
}
84
- console . log ( `[CodSpeed] Done running ${ suite . length } benches. ` ) ;
85
- return suite ;
86
- } ;
87
- return suite ;
192
+ console . log ( ` ✔ Measured ${ uri } ` ) ;
193
+ benchmarkCompletedListeners . forEach ( ( listener ) => listener ( ) ) ;
194
+ }
195
+ console . log ( `[CodSpeed] Done running ${ benches . length } benches.` ) ;
88
196
}
89
197
90
198
function getCallingFile ( ) : string {
@@ -101,6 +209,6 @@ function getGitDir(path: string): string | undefined {
101
209
const dotGitPath = findUpSync ( ".git" , {
102
210
cwd : path ,
103
211
type : "directory" ,
104
- } as Options ) ;
212
+ } as FindupOptions ) ;
105
213
return dotGitPath ? dirname ( dotGitPath ) : undefined ;
106
214
}
0 commit comments