93 lines
3 KiB
TypeScript
93 lines
3 KiB
TypeScript
import { chromium } from "playwright"
|
|
|
|
// Start the Vite dev server (it serves the COOP/COEP headers needed for
|
|
// SharedArrayBuffer), drive real headless Chromium through both bench modes, and
|
|
// read the timings back. Real V8 + Web Workers + SAB + rAF -- the environment my
|
|
// headless Bun benches can't see.
|
|
|
|
const PORT = 5199
|
|
const URL = `http://localhost:${PORT}`
|
|
|
|
const vite = Bun.spawn(["bunx", "--bun", "vite", "--port", String(PORT), "--strictPort"], {
|
|
cwd: import.meta.dir + "/..",
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
env: { ...process.env, NO_COLOR: "1" },
|
|
})
|
|
|
|
async function waitForServer(): Promise<void> {
|
|
for (let i = 0; i < 150; i++) {
|
|
try {
|
|
const r = await fetch(URL + "/")
|
|
if (r.ok) {
|
|
return
|
|
}
|
|
} catch {
|
|
// not up yet
|
|
}
|
|
await Bun.sleep(200)
|
|
}
|
|
throw new Error("vite dev server did not start")
|
|
}
|
|
|
|
type Bench = {
|
|
mode: string
|
|
parallel: boolean
|
|
cores: number
|
|
coi: boolean
|
|
res: string
|
|
workMs: { median: number; p95: number; max: number; mean: number }
|
|
frameMs: { median: number; p95: number; max: number; mean: number }
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
await waitForServer()
|
|
const browser = await chromium.launch({
|
|
headless: true,
|
|
args: [
|
|
"--enable-features=SharedArrayBuffer",
|
|
"--disable-background-timer-throttling",
|
|
"--disable-renderer-backgrounding",
|
|
"--disable-backgrounding-occluded-windows",
|
|
],
|
|
})
|
|
|
|
async function run(mode: string): Promise<Bench> {
|
|
const page = await browser.newPage()
|
|
page.on("pageerror", (e) => console.log(` [page error] ${e.message}`))
|
|
page.on("console", (m) => {
|
|
const t = m.text()
|
|
if (t.startsWith("BENCH") || m.type() === "error") {
|
|
console.log(` [console] ${t}`)
|
|
}
|
|
})
|
|
await page.setViewportSize({ width: 800, height: 600 })
|
|
await page.goto(`${URL}/?bench=${mode}`, { waitUntil: "load" })
|
|
await page.waitForFunction("window.__BENCH__ !== undefined", null, { timeout: 120000 })
|
|
const result = (await page.evaluate("window.__BENCH__")) as Bench
|
|
await page.close()
|
|
return result
|
|
}
|
|
|
|
console.log("--- single-thread ---")
|
|
const st = await run("st")
|
|
console.log("--- workers ---")
|
|
const mt = await run("mt")
|
|
await browser.close()
|
|
|
|
const line = (b: Bench) =>
|
|
`parallel=${b.parallel} coi=${b.coi} cores=${b.cores} res=${b.res} work med/p95/max = ${b.workMs.median}/${b.workMs.p95}/${b.workMs.max} ms frame med/p95 = ${b.frameMs.median}/${b.frameMs.p95} ms`
|
|
console.log("")
|
|
console.log(`single-thread : ${line(st)}`)
|
|
console.log(`workers : ${line(mt)}`)
|
|
console.log("")
|
|
console.log(`work median : ${st.workMs.median} -> ${mt.workMs.median} ms (${(st.workMs.median / mt.workMs.median).toFixed(2)}x)`)
|
|
console.log(`work p95 : ${st.workMs.p95} -> ${mt.workMs.p95} ms (${(st.workMs.p95 / mt.workMs.p95).toFixed(2)}x)`)
|
|
console.log(`frame p95 : ${st.frameMs.p95} -> ${mt.frameMs.p95} ms (jitter: lower p95/median = steadier)`)
|
|
}
|
|
|
|
try {
|
|
await main()
|
|
} finally {
|
|
vite.kill()
|
|
}
|