-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathindex.ts
More file actions
115 lines (94 loc) · 3.19 KB
/
index.ts
File metadata and controls
115 lines (94 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import {
InstrumentHooks,
setupCore,
writeWalltimeResults,
} from "@codspeed/core";
import { Fn } from "tinybench";
import {
RunnerTaskEventPack,
RunnerTaskResultPack,
type RunnerTestSuite,
} from "vitest";
import { NodeBenchmarkRunner } from "../compat";
import { patchRootSuiteWithFullFilePath } from "../common";
import { extractBenchmarkResults } from "./utils";
/**
* WalltimeRunner uses Vitest's default benchmark execution
* and extracts results from the suite after completion
*/
export class WalltimeRunner extends NodeBenchmarkRunner {
private isTinybenchHookedWithCodspeed = false;
private suiteUris = new Map<string, string>();
/// Suite ID of the currently running suite, to allow constructing the URI in the context of tinybench tasks
private currentSuiteId: string | null = null;
async runSuite(suite: RunnerTestSuite): Promise<void> {
patchRootSuiteWithFullFilePath(suite);
this.populateBenchmarkUris(suite);
setupCore();
await super.runSuite(suite);
const benchmarks = await extractBenchmarkResults(suite);
if (benchmarks.length > 0) {
writeWalltimeResults(benchmarks);
console.log(
`[CodSpeed] Done collecting walltime data for ${benchmarks.length} benches.`
);
} else {
console.warn(
`[CodSpeed] No benchmark results found after suite execution`
);
}
}
private populateBenchmarkUris(suite: RunnerTestSuite, parentPath = ""): void {
const currentPath =
parentPath !== "" ? `${parentPath}::${suite.name}` : suite.name;
for (const task of suite.tasks) {
if (task.type === "suite") {
this.suiteUris.set(task.id, `${currentPath}::${task.name}`);
this.populateBenchmarkUris(task, currentPath);
}
}
}
async importTinybench(): Promise<typeof import("tinybench")> {
const tinybench = await super.importTinybench();
if (this.isTinybenchHookedWithCodspeed) {
return tinybench;
}
this.isTinybenchHookedWithCodspeed = true;
const originalRun = tinybench.Task.prototype.run;
const getSuiteUri = (): string => {
if (this.currentSuiteId === null) {
throw new Error("currentSuiteId is null - something went wrong");
}
return this.suiteUris.get(this.currentSuiteId) || "";
};
tinybench.Task.prototype.run = async function () {
const { fn } = this as { fn: Fn };
const suiteUri = getSuiteUri();
function __codspeed_root_frame__() {
return fn();
}
(this as { fn: Fn }).fn = __codspeed_root_frame__;
InstrumentHooks.startBenchmark();
await originalRun.call(this);
InstrumentHooks.stopBenchmark();
// Look up the URI by task name
const uri = `${suiteUri}::${this.name}`;
InstrumentHooks.setExecutedBenchmark(process.pid, uri);
return this;
};
return tinybench;
}
// Allow tinybench to retrieve the path to the currently running suite
async onTaskUpdate(
_: RunnerTaskResultPack[],
events: RunnerTaskEventPack[]
): Promise<void> {
events.map((event) => {
const [id, eventName] = event;
if (eventName === "suite-prepare") {
this.currentSuiteId = id;
}
});
}
}
export default WalltimeRunner;