-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrunner.ts
More file actions
119 lines (99 loc) · 3.39 KB
/
runner.ts
File metadata and controls
119 lines (99 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// @ts-nocheck
import { chromium, type Page, type Browser } from "playwright";
import cliProgress from "cli-progress";
const ITERATIONS = 100;
const SIZES = ["small", "big"] as const;
const LIBS = ["datastar", "datastar-replace", "htmx", "idiomorph", "jquery", "vanilla"] as const;
const BASE_URL = "http://localhost:3000";
declare global {
interface Window {
benchmarkResults: Array<{ lib: string; ms: number; timestamp: number }>;
}
}
interface Sample {
lib: string;
size: string;
ms: number;
}
const PROGRESS_CONFIG = {
format: 'Benchmark |{bar}| {percentage}% | {value}/{total} | ETA: {eta}s | {lib}/{size} ({iteration}) | Last: {lastTime}',
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
hideCursor: true,
stopOnComplete: true,
clearOnComplete: false
};
async function collectSamples(
page: Page,
lib: string,
size: string,
progressBar: cliProgress.SingleBar
): Promise<Sample[]> {
const samples: Sample[] = [];
await page.goto(`${BASE_URL}/${lib}`);
await page.waitForLoadState('domcontentloaded');
for (let i = 0; i < ITERATIONS; i++) {
await page.evaluate(() => { window.benchmarkResults = []; });
await page.click(`#${size}`);
const result = await page.waitForFunction(() => {
return window.benchmarkResults?.length > 0
? window.benchmarkResults[window.benchmarkResults.length - 1]
: false;
});
const benchmarkData = await result.jsonValue();
samples.push({ lib: benchmarkData.lib, size, ms: benchmarkData.ms });
progressBar.increment(1, {
lib,
size,
iteration: `${i + 1}/${ITERATIONS}`,
lastTime: `${benchmarkData.ms.toFixed(2)}ms`
});
}
return samples;
}
function calculateMedian(values: number[]): number {
const sorted = [...values].sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
}
function createProgressBar(): cliProgress.SingleBar {
const totalOperations = SIZES.length * LIBS.length * ITERATIONS;
const progressBar = new cliProgress.SingleBar(PROGRESS_CONFIG, cliProgress.Presets.shades_classic);
console.log(`Starting benchmark: ${SIZES.length} sizes × ${LIBS.length} libs × ${ITERATIONS} iterations = ${totalOperations} total operations\n`);
progressBar.start(totalOperations, 0, { lib: '', size: '', iteration: '', lastTime: '' });
return progressBar;
}
function printResults(samples: Sample[]): void {
for (const size of SIZES) {
console.log(`\n=== ${size}.html (median) ===`);
for (const lib of LIBS) {
const subset = samples.filter(s => s.lib === lib && s.size === size);
const times = subset.map(s => s.ms);
const medianTime = calculateMedian(times);
console.log(lib.padEnd(10), medianTime.toFixed(2) + " ms");
}
}
}
async function runBenchmark(): Promise<void> {
let browser: Browser | null = null;
try {
browser = await chromium.launch();
const page = await browser.newPage();
const progressBar = createProgressBar();
const allSamples: Sample[] = [];
for (const size of SIZES) {
for (const lib of LIBS) {
const samples = await collectSamples(page, lib, size, progressBar);
allSamples.push(...samples);
}
}
progressBar.stop();
console.log('\n');
printResults(allSamples);
} finally {
if (browser) {
await browser.close();
}
}
}
await runBenchmark();