Skip to content

Commit 6688f9a

Browse files
GuillaumeLagrangeart049
authored andcommitted
feat(vitest-plugin): add perf profiling for vitest plugin
1 parent 2194b10 commit 6688f9a

File tree

3 files changed

+86
-3
lines changed

3 files changed

+86
-3
lines changed

packages/vitest-plugin/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
"@codspeed/core": "workspace:^4.0.1"
3232
},
3333
"peerDependencies": {
34+
"tinybench": "^2.9.0",
3435
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",
3536
"vitest": ">=3.2"
3637
},
3738
"devDependencies": {
3839
"@total-typescript/shoehorn": "^0.1.1",
3940
"execa": "^8.0.1",
41+
"tinybench": "^2.9.0",
4042
"vite": "^7.0.0",
4143
"vitest": "^3.2.4"
4244
}

packages/vitest-plugin/src/walltime/index.ts

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
import { setupCore, writeWalltimeResults } from "@codspeed/core";
2-
import { type RunnerTestSuite } from "vitest";
1+
import {
2+
InstrumentHooks,
3+
setupCore,
4+
writeWalltimeResults,
5+
} from "@codspeed/core";
6+
import { Fn } from "tinybench";
7+
import {
8+
RunnerTaskEventPack,
9+
RunnerTaskResultPack,
10+
type RunnerTestSuite,
11+
} from "vitest";
312
import { NodeBenchmarkRunner } from "vitest/runners";
413
import { patchRootSuiteWithFullFilePath } from "../common";
514
import { extractBenchmarkResults } from "./utils";
@@ -10,10 +19,13 @@ import { extractBenchmarkResults } from "./utils";
1019
*/
1120
export class WalltimeRunner extends NodeBenchmarkRunner {
1221
private isTinybenchHookedWithCodspeed = false;
13-
private benchmarkUris = new Map<string, string>();
22+
private suiteUris = new Map<string, string>();
23+
/// Suite ID of the currently running suite, to allow constructing the URI in the context of tinybench tasks
24+
private currentSuiteId: string | null = null;
1425

1526
async runSuite(suite: RunnerTestSuite): Promise<void> {
1627
patchRootSuiteWithFullFilePath(suite);
28+
this.populateBenchmarkUris(suite);
1729

1830
setupCore();
1931

@@ -32,6 +44,72 @@ export class WalltimeRunner extends NodeBenchmarkRunner {
3244
);
3345
}
3446
}
47+
48+
private populateBenchmarkUris(suite: RunnerTestSuite, parentPath = ""): void {
49+
const currentPath =
50+
parentPath !== "" ? `${parentPath}::${suite.name}` : suite.name;
51+
52+
for (const task of suite.tasks) {
53+
if (task.type === "suite") {
54+
this.suiteUris.set(task.id, `${currentPath}::${task.name}`);
55+
this.populateBenchmarkUris(task, currentPath);
56+
}
57+
}
58+
}
59+
60+
async importTinybench(): Promise<typeof import("tinybench")> {
61+
const tinybench = await super.importTinybench();
62+
63+
if (this.isTinybenchHookedWithCodspeed) {
64+
return tinybench;
65+
}
66+
this.isTinybenchHookedWithCodspeed = true;
67+
68+
const originalRun = tinybench.Task.prototype.run;
69+
70+
const getSuiteUri = (): string => {
71+
if (this.currentSuiteId === null) {
72+
throw new Error("currentSuiteId is null - something went wrong");
73+
}
74+
return this.suiteUris.get(this.currentSuiteId) || "";
75+
};
76+
77+
tinybench.Task.prototype.run = async function () {
78+
const { fn } = this as { fn: Fn };
79+
const suiteUri = getSuiteUri();
80+
81+
function __codspeed_root_frame__() {
82+
return fn();
83+
}
84+
(this as { fn: Fn }).fn = __codspeed_root_frame__;
85+
86+
InstrumentHooks.startBenchmark();
87+
await originalRun.call(this);
88+
InstrumentHooks.stopBenchmark();
89+
90+
// Look up the URI by task name
91+
const uri = `${suiteUri}::${this.name}`;
92+
InstrumentHooks.setExecutedBenchmark(process.pid, uri);
93+
94+
return this;
95+
};
96+
97+
return tinybench;
98+
}
99+
100+
// Allow tinybench to retrieve the path to the currently running suite
101+
async onTaskUpdate(
102+
_: RunnerTaskResultPack[],
103+
events: RunnerTaskEventPack[]
104+
): Promise<void> {
105+
events.map((event) => {
106+
const [id, eventName] = event;
107+
108+
if (eventName === "suite-prepare") {
109+
this.currentSuiteId = id;
110+
}
111+
});
112+
}
35113
}
36114

37115
export default WalltimeRunner;

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)