mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-11 09:51:30 +00:00
116 lines
4.3 KiB
TypeScript
116 lines
4.3 KiB
TypeScript
import { test } from '../../../playwright';
|
|
import { type ElectronApplication, type Page } from '@playwright/test';
|
|
import { openCollection, closeAllCollections } from '../../utils/page';
|
|
import { summarize } from '../utils/stats';
|
|
import { writeResults, buildResultEntry, type ResultEntry } from '../utils/results';
|
|
import { startTimer } from '../utils/timing';
|
|
import { generateCollection, type CollectionFormat } from '../utils/collection-generator';
|
|
import * as path from 'path';
|
|
import * as fs from 'fs';
|
|
|
|
const COLLECTION_SIZES = [50, 200, 500, 1000, 3000];
|
|
const COLLECTION_FORMATS: CollectionFormat[] = ['bru', 'yml'];
|
|
const ITERATIONS_PER_SIZE = 3;
|
|
|
|
async function measureCollectionMount(
|
|
page: Page,
|
|
electronApp: ElectronApplication,
|
|
collectionDir: string,
|
|
collectionName: string
|
|
): Promise<number> {
|
|
await electronApp.evaluate(
|
|
({ dialog }, { dir }) => {
|
|
(dialog as any).__originalShowOpenDialog ??= dialog.showOpenDialog;
|
|
dialog.showOpenDialog = async () => ({ canceled: false, filePaths: [dir] });
|
|
},
|
|
{ dir: collectionDir }
|
|
);
|
|
|
|
await page.evaluate(() => {
|
|
(window as any).__benchMountDone = new Promise<void>((resolve) => {
|
|
const off = (window as any).ipcRenderer.on('main:collection-loading-state-updated', (val: any) => {
|
|
if (!val.isLoading) {
|
|
off(); resolve();
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
const timer = startTimer();
|
|
|
|
await page.getByTestId('collections-header-add-menu').click();
|
|
await page.locator('.tippy-box .dropdown-item').filter({ hasText: 'Open collection' }).click();
|
|
await page.locator('#sidebar-collection-name').filter({ hasText: collectionName }).waitFor({ state: 'visible' });
|
|
|
|
await openCollection(page, collectionName);
|
|
await page.evaluate(() => (window as any).__benchMountDone);
|
|
|
|
const elapsed = timer.elapsed();
|
|
|
|
await electronApp.evaluate(({ dialog }) => {
|
|
if ((dialog as any).__originalShowOpenDialog) {
|
|
dialog.showOpenDialog = (dialog as any).__originalShowOpenDialog;
|
|
}
|
|
});
|
|
|
|
await closeAllCollections(page);
|
|
|
|
return elapsed;
|
|
}
|
|
|
|
function resultKey(format: CollectionFormat, size: number): string {
|
|
return `${format}-${size}`;
|
|
}
|
|
|
|
test.describe('Benchmark: Collection Mount', () => {
|
|
const results: Record<string, number[]> = {};
|
|
|
|
for (const format of COLLECTION_FORMATS) {
|
|
test.describe(`format: ${format}`, () => {
|
|
for (const size of COLLECTION_SIZES) {
|
|
test(`mount ${format} collection with ${size} requests`, async ({ page, electronApp, createTmpDir }) => {
|
|
test.setTimeout((2 + Math.ceil(size / 100) * 2) * 60_000);
|
|
const timings: number[] = [];
|
|
|
|
const collectionName = `bench-${format}-${size}`;
|
|
const collectionDir = await createTmpDir(`bench-${format}-${size}`);
|
|
generateCollection({ dir: collectionDir, name: collectionName, requestCount: size, format });
|
|
|
|
for (let i = 0; i < ITERATIONS_PER_SIZE; i++) {
|
|
const elapsed = await measureCollectionMount(page, electronApp, collectionDir, collectionName);
|
|
timings.push(elapsed);
|
|
}
|
|
|
|
const key = resultKey(format, size);
|
|
results[key] = timings;
|
|
|
|
const stats = summarize(timings);
|
|
const r = (v: number) => Math.round(v);
|
|
console.log(`[BENCHMARK] ${format} ${size} requests — mean: ${r(stats.mean)}ms, median: ${r(stats.median)}ms, p90: ${r(stats.p90)}ms, stdDev: ${r(stats.stdDev)}ms, raw: [${timings.join(', ')}]`);
|
|
|
|
test.info().annotations.push({
|
|
type: 'benchmark',
|
|
description: JSON.stringify({ format, size, ...stats, timings })
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
test.afterAll(async () => {
|
|
const resultsDir = path.join(process.cwd(), 'tests', 'benchmarks', 'results');
|
|
fs.mkdirSync(resultsDir, { recursive: true });
|
|
const outputPath = path.join(resultsDir, 'mounting.json');
|
|
const entries: Record<string, ResultEntry> = {};
|
|
|
|
for (const [key, timings] of Object.entries(results)) {
|
|
if (timings.length === 0) continue;
|
|
const [format, sizeStr] = key.split('-');
|
|
entries[key] = buildResultEntry(timings, { format, size: Number(sizeStr) });
|
|
}
|
|
|
|
writeResults(outputPath, { name: 'Collection Mount', unit: 'ms', direction: 'smaller' }, entries);
|
|
console.log(`[BENCHMARK] Results written to ${outputPath}`);
|
|
});
|
|
});
|