|
1 | 1 | import { |
2 | 2 | getGitDir, |
| 3 | + getMeasurementMode, |
3 | 4 | Measurement, |
| 5 | + MeasurementMode, |
4 | 6 | mongoMeasurement, |
5 | | - optimizeFunction, |
6 | | - setupCore, |
7 | 7 | SetupInstrumentsRequestBody, |
8 | 8 | SetupInstrumentsResponse, |
9 | | - teardownCore, |
10 | 9 | tryIntrospect, |
11 | 10 | } from "@codspeed/core"; |
12 | 11 | import path from "path"; |
13 | 12 | import { get as getStackTrace } from "stack-trace"; |
14 | | -import { Bench, Task } from "tinybench"; |
| 13 | +import { Bench } from "tinybench"; |
15 | 14 | import { fileURLToPath } from "url"; |
16 | | - |
17 | | -declare const __VERSION__: string; |
| 15 | +import { runInstrumentedBench } from "./instrumented"; |
| 16 | +import { runWalltimeBench } from "./walltime"; |
18 | 17 |
|
19 | 18 | tryIntrospect(); |
20 | 19 |
|
21 | | -type CodSpeedBenchOptions = Task["opts"] & { |
22 | | - uri: string; |
23 | | -}; |
24 | | - |
25 | | -function isCodSpeedBenchOptions( |
26 | | - options: Task["opts"] |
27 | | -): options is CodSpeedBenchOptions { |
28 | | - return "uri" in options; |
29 | | -} |
| 20 | +// Store URI mapping externally since fnOpts is private |
| 21 | +export const taskUriMap = new WeakMap<Bench, Map<string, string>>(); |
30 | 22 |
|
31 | 23 | export function withCodSpeed(bench: Bench): Bench { |
32 | | - if (!Measurement.isInstrumented()) { |
| 24 | + const measurementMode = getMeasurementMode(); |
| 25 | + const rootCallingFile = getCallingFile(); |
| 26 | + |
| 27 | + // Initialize URI mapping for this bench instance |
| 28 | + if (!taskUriMap.has(bench)) { |
| 29 | + taskUriMap.set(bench, new Map()); |
| 30 | + } |
| 31 | + const uriMap = taskUriMap.get(bench)!; |
| 32 | + |
| 33 | + // Setup URI generation for tasks |
| 34 | + const rawAdd = bench.add; |
| 35 | + bench.add = (name, fn, opts?) => { |
| 36 | + const callingFile = getCallingFile(); |
| 37 | + const uri = `${callingFile}::${name}`; |
| 38 | + // Store URI mapping |
| 39 | + uriMap.set(name, uri); |
| 40 | + return rawAdd.bind(bench)(name, fn, opts); |
| 41 | + }; |
| 42 | + |
| 43 | + // Apply the appropriate measurement strategy based on mode and instrumentation |
| 44 | + if ( |
| 45 | + measurementMode === MeasurementMode.Instrumentation && |
| 46 | + Measurement.isInstrumented() |
| 47 | + ) { |
| 48 | + runInstrumentedBench(bench, rootCallingFile); |
| 49 | + } else if (measurementMode === MeasurementMode.WallTime) { |
| 50 | + runWalltimeBench(bench, rootCallingFile); |
| 51 | + } else { |
| 52 | + // Fallback: instrumentation requested but not available |
33 | 53 | const rawRun = bench.run; |
34 | 54 | bench.run = async () => { |
35 | 55 | console.warn( |
36 | 56 | `[CodSpeed] ${bench.tasks.length} benches detected but no instrumentation found, falling back to tinybench` |
37 | 57 | ); |
38 | 58 | return await rawRun.bind(bench)(); |
39 | 59 | }; |
40 | | - return bench; |
41 | 60 | } |
42 | 61 |
|
43 | | - const rawAdd = bench.add; |
44 | | - bench.add = (name, fn, opts: CodSpeedBenchOptions) => { |
45 | | - const callingFile = getCallingFile(); |
46 | | - const uri = `${callingFile}::${name}`; |
47 | | - const options = Object.assign({}, opts ?? {}, { uri }); |
48 | | - return rawAdd.bind(bench)(name, fn, options); |
49 | | - }; |
50 | | - const rootCallingFile = getCallingFile(); |
51 | | - |
52 | | - bench.run = async () => { |
53 | | - console.log(`[CodSpeed] running with @codspeed/tinybench v${__VERSION__}`); |
54 | | - setupCore(); |
55 | | - for (const task of bench.tasks) { |
56 | | - const uri = isCodSpeedBenchOptions(task.opts) |
57 | | - ? task.opts.uri |
58 | | - : `${rootCallingFile}::${task.name}`; |
59 | | - |
60 | | - await task.opts.beforeAll?.call(task); |
61 | | - |
62 | | - // run optimizations |
63 | | - await optimizeFunction(async () => { |
64 | | - await task.opts.beforeEach?.call(task); |
65 | | - await task.fn(); |
66 | | - await task.opts.afterEach?.call(task); |
67 | | - }); |
68 | | - |
69 | | - // run instrumented benchmark |
70 | | - await task.opts.beforeEach?.call(task); |
71 | | - |
72 | | - await mongoMeasurement.start(uri); |
73 | | - global.gc?.(); |
74 | | - await (async function __codspeed_root_frame__() { |
75 | | - Measurement.startInstrumentation(); |
76 | | - await task.fn(); |
77 | | - Measurement.stopInstrumentation(uri); |
78 | | - })(); |
79 | | - await mongoMeasurement.stop(uri); |
80 | | - |
81 | | - await task.opts.afterEach?.call(task); |
82 | | - |
83 | | - await task.opts.afterAll?.call(task); |
84 | | - |
85 | | - // print results |
86 | | - console.log(` ✔ Measured ${uri}`); |
87 | | - } |
88 | | - teardownCore(); |
89 | | - console.log(`[CodSpeed] Done running ${bench.tasks.length} benches.`); |
90 | | - return bench.tasks; |
91 | | - }; |
92 | 62 | return bench; |
93 | 63 | } |
94 | 64 |
|
|
0 commit comments