// Real-browser benchmark (Playwright Chromium): @uhhm/buuh-html vs µhtml v5, // same create/update scenarios as bench/render.js but with native DOM. // nanohtml v1 is CJS-only and can't be import-mapped, so it only appears // in the happy-dom bench. // // node bench/real-browser.js import { chromium } from 'playwright' import { startServer } from '../test/e2e/serve.js' const srv = await startServer() const browser = await chromium.launch() const page = await browser.newPage() const PAGE = ` ` await page.route('**/bench-page', (route) => route.fulfill({ contentType: 'text/html', body: PAGE })) await page.goto(srv.origin + '/bench-page') const results = await page.evaluate(async () => { const { default: html } = await import('@uhhm/buuh-html') const { default: morph } = await import('@uhhm/buuh-html/morph') const { html: uhtml, render: urender } = await import('uhtml') const ROWS = 100 const data = (tick) => Array.from({ length: ROWS }, (_, i) => ({ id: i, label: 'row ' + i + ' rev ' + tick, selected: i === tick % ROWS })) const bench = (fn) => { let t = 0 const warmupEnd = performance.now() + 200 while (performance.now() < warmupEnd) fn(t++) let ops = 0 const start = performance.now() const end = start + 1000 while (performance.now() < end) { fn(t++); ops++ } return Math.round((ops / (performance.now() - start)) * 1000) } const ourTable = (rows) => html`${rows.map((r) => html``)}
${r.id}${r.label}
` const uTable = (rows) => uhtml`${rows.map((r) => uhtml``)}
${r.id}${r.label}
` const out = {} out['@uhhm/buuh-html create'] = bench((t) => ourTable(data(t))) out['uhtml v5 create (fresh container)'] = bench((t) => { const c = document.createElement('div') urender(c, uTable(data(t))) }) const live = ourTable(data(0)) document.body.appendChild(live) out['@uhhm/buuh-html + nanomorph update'] = bench((t) => morph(live, ourTable(data(t)))) live.remove() const c = document.createElement('div') document.body.appendChild(c) out['uhtml v5 update (in place)'] = bench((t) => urender(c, uTable(data(t)))) c.remove() return out }) console.log('\nreal Chromium — 100-row table, ops/s:') for (const [name, ops] of Object.entries(results)) { console.log(' ' + name.padEnd(38) + String(ops).padStart(8) + ' ops/s') } console.log() await browser.close() await srv.close()