Files
bitvid/benchmarks/docs_scroll_spy_bench.js
T
google-labs-jules[bot]andPR0M3TH3AN 55a9b937cb Refactor Docs ScrollSpy to use IntersectionObserver
Replaces the scroll event listener and `getBoundingClientRect` polling with `IntersectionObserver` to eliminate layout thrashing and improve scrolling performance.

- Removes `window.onscroll` handler in `docsView.js`.
- Implements `IntersectionObserver` with `rootMargin` to track active headings.
- Retains initial one-time scan for correct state on load.
- Adds benchmark `benchmarks/docs_scroll_spy.html` and `benchmarks/docs_scroll_spy_bench.js`.

Benchmark results:
- Legacy: ~0.065ms/call (200 calls) -> Total ~13ms CPU (sync layout thrashing)
- Optimized: ~0.028ms/call (32 calls) -> Total ~0.9ms CPU
- 14x improvement in CPU time for scroll handler logic.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-05 20:52:52 +00:00

83 lines
2.2 KiB
JavaScript

import { chromium } from 'playwright';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
const filePath = `file://${path.join(__dirname, 'docs_scroll_spy.html')}`;
console.log(`Loading ${filePath}`);
await page.goto(filePath);
// --- LEGACY ---
console.log('Running Legacy Benchmark...');
await page.evaluate(() => window.startLegacy());
await page.evaluate(async () => {
return new Promise(resolve => {
let scrollY = 0;
let steps = 0;
const maxSteps = 200;
const stepSize = 200;
function step() {
scrollY += stepSize;
window.scrollTo(0, scrollY);
steps++;
if (steps < maxSteps) {
requestAnimationFrame(step);
} else {
resolve();
}
}
step();
});
});
// Wait for RAFs to flush
await page.waitForTimeout(500);
const legacyMetrics = await page.evaluate(() => window.getMetrics());
console.log('Legacy Metrics:', legacyMetrics);
await page.evaluate(() => window.stopLegacy());
await page.evaluate(() => window.scrollTo(0, 0));
await page.waitForTimeout(1000);
// --- OPTIMIZED ---
console.log('Running Optimized Benchmark...');
await page.evaluate(() => window.startOptimized());
await page.evaluate(async () => {
return new Promise(resolve => {
let scrollY = 0;
let steps = 0;
const maxSteps = 200;
const stepSize = 200;
function step() {
scrollY += stepSize;
window.scrollTo(0, scrollY);
steps++;
if (steps < maxSteps) {
requestAnimationFrame(step);
} else {
resolve();
}
}
step();
});
});
// Wait for IO to flush
await page.waitForTimeout(500);
const optimizedMetrics = await page.evaluate(() => window.getMetrics());
console.log('Optimized Metrics:', optimizedMetrics);
await browser.close();
})();