Skip to content

Commit b943512

Browse files
fix(vitest-plugin)!: disable vitest 5 export getter tracking under codspeed
Vitest 5 wraps every module export getter with a diagnostic counter (a Map lookup and write per access) unless benchmark.suppressExportGetterWarnings is set. That counter runs inside the measured code, inflating results: a bench reading an export 100k times measures 109M instructions on Vitest 5 versus 38M on Vitest 4. Default the option to true when the plugin is active, keeping any value the user sets explicitly. Plain `vitest bench` runs are unaffected. With this, the same bench measures the same instruction count on Vitest 4 and 5. Drop the import hoisting from the benches and examples: it only worked around the tracker. Closes COD-3892 Closes #98 Co-Authored-By: Claude <noreply@anthropic.com>
1 parent c2a065e commit b943512

7 files changed

Lines changed: 28 additions & 28 deletions

File tree

‎examples/with-typescript-esm/src/fibonacci.bench.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import { describe, test } from "vitest";
2-
import { recursiveFibonacci as recursiveFibonacciExport } from "./fibonacci";
3-
4-
// Imports are getters under Vite's module runner; read them once, outside the
5-
// measured loop.
6-
const recursiveFibonacci = recursiveFibonacciExport;
2+
import { recursiveFibonacci } from "./fibonacci";
73

84
describe("recursiveFibonacci", () => {
95
test("fibo 30", async ({ bench }) => {

‎examples/with-vitest-v5/src/fibonacci.bench.ts‎

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
import { describe, test } from "vitest";
2-
import {
3-
iterativeFibonacci as iterativeFibonacciExport,
4-
recursiveFibonacci as recursiveFibonacciExport,
5-
} from "./fibonacci";
6-
7-
// Imports are getters under Vite's module runner; read them once, outside the
8-
// measured loop.
9-
const recursiveFibonacci = recursiveFibonacciExport;
10-
const iterativeFibonacci = iterativeFibonacciExport;
2+
import { iterativeFibonacci, recursiveFibonacci } from "./fibonacci";
113

124
describe("fibonacci", () => {
135
test("fibo 15", async ({ bench }) => {

‎packages/vitest-plugin/benches/flat.bench.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import { describe, test } from "vitest";
2-
import parsePrExport from "./parsePr";
3-
4-
// Imports are getters under Vite's module runner; read it once, outside the
5-
// measured loop.
6-
const parsePr = parsePrExport;
2+
import parsePr from "./parsePr";
73

84
const LONG_BODY =
95
new Array(1_000)

‎packages/vitest-plugin/benches/parsePr.bench.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import { describe, test } from "vitest";
2-
import parsePrExport from "./parsePr";
3-
4-
// Imports are getters under Vite's module runner; read it once, outside the
5-
// measured loop.
6-
const parsePr = parsePrExport;
2+
import parsePr from "./parsePr";
73

84
const LONG_BODY =
95
new Array(1_000)

‎packages/vitest-plugin/src/__tests__/index.test.ts‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { getV8Flags } from "@codspeed/core";
22
import { fromPartial } from "@total-typescript/shoehorn";
33
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4+
import { type ViteUserConfig } from "vitest/config";
45
import codspeedPlugin from "../index";
56

67
const coreMocks = vi.hoisted(() => {
@@ -34,10 +35,10 @@ function apply(mode: string) {
3435
return plugin.apply({}, fromPartial({ mode }));
3536
}
3637

37-
function config() {
38+
function config(userConfig: ViteUserConfig = {}) {
3839
if (typeof plugin.config !== "function")
3940
throw new Error("config is not a function");
40-
return plugin.config.call({} as never, {}, fromPartial({}));
41+
return plugin.config.call({} as never, userConfig, fromPartial({}));
4142
}
4243

4344
describe("codSpeedPlugin", () => {
@@ -148,9 +149,18 @@ describe("codSpeedPlugin", () => {
148149
provider: expect.stringContaining(
149150
"packages/vitest-plugin/src/v5/provider.ts",
150151
),
152+
suppressExportGetterWarnings: true,
151153
},
152154
},
153155
});
154156
});
157+
158+
it("should keep an explicit suppressExportGetterWarnings from the user", () => {
159+
const result = config({
160+
test: { benchmark: { suppressExportGetterWarnings: false } },
161+
}) as ViteUserConfig;
162+
163+
expect(result.test?.benchmark?.suppressExportGetterWarnings).toBe(false);
164+
});
155165
});
156166
});

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@ export default function codspeedPlugin(): Plugin {
3737
return true;
3838
},
3939
enforce: "post",
40-
config(): ViteUserConfig {
40+
config(userConfig): ViteUserConfig {
4141
return {
4242
test: {
4343
pool: "forks",
4444
globalSetup: [resolveFile("globalSetup")],
4545
...resolveVitestBackend().getBenchmarkTestConfig(
4646
getV8Flags(),
4747
resolveFile,
48+
(userConfig as ViteUserConfig).test,
4849
),
4950
},
5051
};

‎packages/vitest-plugin/src/vitestBackend.ts‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface VitestBackend {
1010
getBenchmarkTestConfig(
1111
v8Flags: string[],
1212
resolveFile: (name: string) => string,
13+
userTestConfig: ViteUserConfig["test"],
1314
): ViteUserConfig["test"];
1415
}
1516

@@ -36,10 +37,18 @@ class V5Backend implements VitestBackend {
3637
getBenchmarkTestConfig(
3738
v8Flags: string[],
3839
resolveFile: (name: string) => string,
40+
userTestConfig: ViteUserConfig["test"],
3941
): ViteUserConfig["test"] {
42+
// Vitest's export getter tracker runs inside the measured code; keep it off
43+
// unless the user explicitly configured it.
44+
const suppressExportGetterWarnings =
45+
userTestConfig?.benchmark?.suppressExportGetterWarnings ?? true;
4046
return {
4147
execArgv: v8Flags,
42-
benchmark: { provider: resolveFile("v5/provider") },
48+
benchmark: {
49+
provider: resolveFile("v5/provider"),
50+
suppressExportGetterWarnings,
51+
},
4352
};
4453
}
4554
}

0 commit comments

Comments
 (0)