Skip to content

Commit 1f54834

Browse files
authored
fix(benchmark): run benchmark suites sequentially (#5444)
1 parent 0930c29 commit 1f54834

18 files changed

+151
-71
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ dist
1515
ltex*
1616
.DS_Store
1717
bench/test/*/*/
18-
**/benchmark/bench.json
18+
**/bench.json
1919
**/browser/browser.json
2020
cypress/videos
2121
cypress/downloads

packages/vitest/src/node/config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ export function resolveConfig(
119119
if (resolved.minWorkers)
120120
resolved.minWorkers = Number(resolved.minWorkers)
121121

122-
resolved.fileParallelism ??= true
122+
// run benchmark sequentially by default
123+
resolved.fileParallelism ??= mode !== 'benchmark'
123124

124125
if (!resolved.fileParallelism) {
125126
// ignore user config, parallelism cannot be implemented without limiting workers

packages/vitest/src/runtime/runners/benchmark.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ async function runBenchmarkSuite(suite: Suite, runner: NodeBenchmarkRunner) {
3535
benchmarkSuiteGroup.push(task)
3636
}
3737

38-
if (benchmarkSuiteGroup.length)
39-
await Promise.all(benchmarkSuiteGroup.map(subSuite => runBenchmarkSuite(subSuite, runner)))
38+
// run sub suites sequentially
39+
for (const subSuite of benchmarkSuiteGroup)
40+
await runBenchmarkSuite(subSuite, runner)
4041

4142
if (benchmarkGroup.length) {
4243
const defer = createDefer()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { defineConfig } from 'vitest/config'
2+
3+
export default defineConfig({})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { bench, describe } from "vitest"
2+
import { appendLog, benchOptions, sleepBench } from "./helper";
3+
4+
bench("B1", async () => {
5+
await appendLog("F1 / B1")
6+
await sleepBench();
7+
}, benchOptions)
8+
9+
describe("S1", () => {
10+
bench("B1", async () => {
11+
await appendLog("F1 / S1 / B1")
12+
await sleepBench();
13+
}, benchOptions)
14+
15+
bench("B2", async () => {
16+
await appendLog("F1 / S1 / B2")
17+
await sleepBench();
18+
}, benchOptions)
19+
})
20+
21+
describe("S2", () => {
22+
bench("B1", async () => {
23+
await appendLog("F1 / S2 / B1")
24+
await sleepBench();
25+
}, benchOptions)
26+
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { bench, describe } from "vitest"
2+
import { appendLog, benchOptions, sleepBench } from "./helper";
3+
4+
describe("S1", () => {
5+
bench("B1", async () => {
6+
await appendLog("F2 / S1 / B1")
7+
await sleepBench();
8+
}, benchOptions)
9+
})
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import fs from "node:fs";
2+
3+
const SLEEP_BENCH_MS = Number(process.env["SLEEP_BENCH_MS"] || 10);
4+
const BENCH_ITERATIONS = Number(process.env["BENCH_ITERATIONS"] || 3);
5+
6+
export const sleepBench = () => new Promise(resolve => setTimeout(resolve, SLEEP_BENCH_MS))
7+
8+
export const testLogFile = new URL("./test.log", import.meta.url);
9+
10+
export async function appendLog(data: string) {
11+
await fs.promises.appendFile(testLogFile, data + "\n");
12+
}
13+
14+
export const benchOptions = {
15+
time: 0,
16+
iterations: BENCH_ITERATIONS,
17+
warmupIterations: 0,
18+
warmupTime: 0,
19+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import fs from "node:fs";
2+
import { testLogFile } from "./helper";
3+
4+
export default async function setup() {
5+
await fs.promises.rm(testLogFile, { force: true });
6+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineConfig } from "vitest/config"
2+
3+
// to see the difference better, increase sleep time and iterations e.g. by
4+
// SLEEP_BENCH_MS=100 pnpm -C test/benchmark test bench -- --root fixtures/sequential --fileParallelism
5+
6+
export default defineConfig({
7+
test: {
8+
globalSetup: ["./setup.ts"]
9+
}
10+
});

test/benchmark/package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
{
2-
"name": "@vitest/benchmark",
2+
"name": "@vitest/benchmark-sequential",
33
"type": "module",
44
"private": true,
55
"scripts": {
6-
"test": "node --test specs/* && echo '1'",
7-
"bench:json": "vitest bench --reporter=json",
8-
"bench": "vitest bench"
6+
"test": "vitest"
97
},
108
"devDependencies": {
119
"vitest": "workspace:*"

test/benchmark/specs/runner.test.mjs

Lines changed: 0 additions & 40 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`sequential 1`] = `
4+
"F1 / S1 / B1
5+
F1 / S1 / B1
6+
F1 / S1 / B1
7+
F1 / S1 / B2
8+
F1 / S1 / B2
9+
F1 / S1 / B2
10+
F1 / S2 / B1
11+
F1 / S2 / B1
12+
F1 / S2 / B1
13+
F1 / B1
14+
F1 / B1
15+
F1 / B1
16+
F2 / S1 / B1
17+
F2 / S1 / B1
18+
F2 / S1 / B1
19+
"
20+
`;

test/benchmark/test/basic.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import fs from 'node:fs'
2+
import { expect, it } from 'vitest'
3+
import * as pathe from 'pathe'
4+
import { runVitest } from '../../test-utils'
5+
6+
it('basic', { timeout: 60_000 }, async () => {
7+
const root = pathe.join(import.meta.dirname, '../fixtures/basic')
8+
const benchFile = pathe.join(root, 'bench.json')
9+
fs.rmSync(benchFile, { force: true })
10+
11+
await runVitest({
12+
root,
13+
allowOnly: true,
14+
benchmark: {
15+
reporters: 'json',
16+
outputFile: 'bench.json',
17+
},
18+
}, [], 'benchmark')
19+
20+
const benchResult = await fs.promises.readFile(benchFile, 'utf-8')
21+
const resultJson = JSON.parse(benchResult)
22+
23+
expect(Object.keys(resultJson.testResults)).toEqual(
24+
expect.arrayContaining([
25+
'sort',
26+
'timeout',
27+
'a0',
28+
'c1',
29+
'a2',
30+
'b3',
31+
'b4',
32+
]),
33+
)
34+
35+
const skipped = ['skip', 's0', 's1', 's2', 's3', 'sb4', 's4', 'unimplemented suite', 'unimplemented test']
36+
for (const b of skipped)
37+
expect(benchResult).not.toContain(b)
38+
})
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import fs from 'node:fs'
2+
import { expect, it } from 'vitest'
3+
import * as pathe from 'pathe'
4+
import { runVitest } from '../../test-utils'
5+
6+
it('sequential', async () => {
7+
const root = pathe.join(import.meta.dirname, '../fixtures/sequential')
8+
await runVitest({ root }, [], 'benchmark')
9+
const testLog = await fs.promises.readFile(pathe.join(root, 'test.log'), 'utf-8')
10+
expect(testLog).toMatchSnapshot()
11+
})

test/benchmark/vitest.config.ts

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,3 @@
11
import { defineConfig } from 'vitest/config'
22

3-
function noop() {}
4-
5-
export default defineConfig({
6-
test: {
7-
update: false,
8-
allowOnly: true,
9-
benchmark: {
10-
outputFile: './bench.json',
11-
reporters: ['json', {
12-
onInit: noop,
13-
onPathsCollected: noop,
14-
onCollected: noop,
15-
onFinished: noop,
16-
onTaskUpdate: noop,
17-
onTestRemoved: noop,
18-
onWatcherStart: noop,
19-
onWatcherRerun: noop,
20-
onServerRestart: noop,
21-
onUserConsoleLog: noop,
22-
}],
23-
},
24-
},
25-
})
3+
export default defineConfig({})

0 commit comments

Comments
 (0)