Skip to content

Commit c34214e

Browse files
committed
feat: Isolate benchmark runs to new browser instances
Ensures each benchmark iteration starts with a completely clean browser state. Launches and closes a new browser instance for every individual benchmark measurement. Refactors the benchmark execution logic into a dedicated function for single page operations. Improves the reliability and accuracy of performance measurements by preventing potential state leakage or side effects between runs.
1 parent 92c90de commit c34214e

File tree

1 file changed

+26
-24
lines changed

1 file changed

+26
-24
lines changed

src/main.js

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -80,29 +80,38 @@ function ensureBenchmarkHtmlTemplates(benchmarkRoot) {
8080
core.endGroup();
8181
}
8282

83-
async function runSingleBenchmark(browser, url, label) {
83+
async function runIsolatedBenchmark(url, label, browserArgs) {
8484
const sampleFPS = [];
8585

8686
for (let i = 0; i < REPEATS; i++) {
87-
const page = await browser.newPage();
88-
await page.setViewportSize({ width: 800, height: 600 });
89-
await page.goto(url, { waitUntil: 'load', timeout: 60_000 });
90-
91-
core.info(`Measurement ${i + 1}/${REPEATS} for ${label}`);
92-
await page.waitForFunction(() => window.benchmarkResult, {
93-
timeout: 60_000
94-
});
95-
const result = await page.evaluate(() => window.benchmarkResult);
96-
sampleFPS.push(result.fps);
97-
await page.close();
87+
const browser = await chromium.launch({ headless: true, args: browserArgs });
88+
await runSingleBenchmark(browser, url, label, sampleFPS, i);
89+
try {
90+
for (const context of browser.contexts()) {
91+
await context.close().catch(() => {});
92+
}
93+
await browser.close();
94+
} catch {}
9895
}
99-
10096
const avg = sampleFPS.reduce((a, b) => a + b, 0) / sampleFPS.length;
10197
const stddev = Math.sqrt(sampleFPS.reduce((s, n) => s + (n - avg) ** 2, 0) / sampleFPS.length);
102-
10398
return { avg, stddev, samples: sampleFPS };
10499
}
105100

101+
async function runSingleBenchmark(browser, url, label, sampleFPS, i) {
102+
const page = await browser.newPage();
103+
await page.setViewportSize({ width: 800, height: 600 });
104+
await page.goto(url, { waitUntil: 'load', timeout: 60_000 });
105+
106+
core.info(`Measurement ${i + 1}/${REPEATS} for ${label}`);
107+
await page.waitForFunction(() => window.benchmarkResult, {
108+
timeout: 60_000
109+
});
110+
const result = await page.evaluate(() => window.benchmarkResult);
111+
sampleFPS.push(result.fps);
112+
await page.close();
113+
}
114+
106115
export async function run() {
107116
let server;
108117
let browser;
@@ -129,14 +138,7 @@ export async function run() {
129138
const indexFiles = findIndexModules(benchmarkFullPath);
130139
if (indexFiles.length === 0) throw new Error('No index.mjs benchmark entrypoints found.');
131140

132-
const browserArgs = [
133-
'--use-gl=angle',
134-
'--disable-web-security'
135-
];
136-
137-
core.startGroup('Launch browser');
138-
browser = await chromium.launch({ headless: true, args: browserArgs });
139-
core.endGroup();
141+
const browserArgs = ['--use-gl=angle', '--disable-web-security'];
140142

141143
const comparisons = [];
142144
core.startGroup('Run dev vs local benchmarks');
@@ -151,8 +153,8 @@ export async function run() {
151153

152154
core.info(`Benchmark: ${name}`);
153155

154-
const devResult = await runSingleBenchmark(browser, devURL, `${name} [dev]`);
155-
const localResult = await runSingleBenchmark(browser, localURL, `${name} [local]`);
156+
const devResult = await runIsolatedBenchmark(devURL, `${name} [dev]`, browserArgs);
157+
const localResult = await runIsolatedBenchmark(localURL, `${name} [local]`, browserArgs);
156158

157159
const diffPercent = ((devResult.avg - localResult.avg) / devResult.avg) * 100;
158160
// Scale allowed difference relative to an optimistic 60fps target.

0 commit comments

Comments
 (0)