117 lines
4.4 KiB
JavaScript
117 lines
4.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* qa-cables-render-probe — replicates the owner-side perf probe methodology
|
|
* for the cables layer (relative numbers; SwiftShader when run headless):
|
|
*
|
|
* 1. PARKED: timed full `viewer.render()` loop (40 calls) with cables ON,
|
|
* then OFF, at the fixed mid-Atlantic camera. Reports mean/max.
|
|
* 2. PAN-STOP: 3 cycles of { setView to an offset, raise camera.moveEnd,
|
|
* wait 650 ms, 20 timed `viewer.render()` calls }. Reports per-cycle
|
|
* mean/max and the worst frame across cycles, cables ON vs OFF.
|
|
*
|
|
* Usage: node scripts/qa-cables-render-probe.mjs [--url http://localhost:4216]
|
|
*/
|
|
import puppeteer from 'puppeteer';
|
|
|
|
const argv = process.argv;
|
|
const url = argv.includes('--url') ? argv[argv.indexOf('--url') + 1] : 'http://localhost:4216';
|
|
const LAYER_ID = 'telegeography-submarine-cables';
|
|
|
|
const browser = await puppeteer.launch({
|
|
headless: 'new',
|
|
protocolTimeout: 300_000,
|
|
args: [
|
|
'--no-sandbox', '--disable-setuid-sandbox', '--window-size=1440,900',
|
|
'--disable-backgrounding-occluded-windows', '--disable-renderer-backgrounding',
|
|
'--disable-background-timer-throttling',
|
|
],
|
|
});
|
|
|
|
try {
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width: 1440, height: 860 });
|
|
await page.goto(url, { waitUntil: 'domcontentloaded' });
|
|
await page.waitForFunction(() => !!window.__godsEyeView?.viewer, { timeout: 90_000 });
|
|
await new Promise((r) => setTimeout(r, 12_000));
|
|
|
|
await page.evaluate(async () => {
|
|
const gev = window.__godsEyeView;
|
|
gev.viewer.camera.cancelFlight();
|
|
const ell = gev.viewer.scene.globe.ellipsoid;
|
|
gev.viewer.camera.setView({
|
|
destination: ell.cartographicToCartesian({
|
|
longitude: -40 * Math.PI / 180, latitude: 35 * Math.PI / 180, height: 4_500_000,
|
|
}),
|
|
orientation: { heading: 0, pitch: -Math.PI / 2, roll: 0 },
|
|
});
|
|
for (const [id, entry] of gev.dataManager.layers) {
|
|
if (entry.enabled) { try { await gev.dataManager.setEnabled(id, false, { origin: 'user' }); } catch { /* probe */ } }
|
|
}
|
|
});
|
|
await new Promise((r) => setTimeout(r, 5_000));
|
|
|
|
const stats = (values) => ({
|
|
mean: +(values.reduce((s, v) => s + v, 0) / Math.max(1, values.length)).toFixed(2),
|
|
max: +Math.max(...values).toFixed(2),
|
|
});
|
|
|
|
const measure = async (label, enabled) => {
|
|
await page.evaluate(async (id, on) => {
|
|
const gev = window.__godsEyeView;
|
|
await gev.dataManager.setEnabled(id, on, { origin: 'user' });
|
|
}, LAYER_ID, enabled);
|
|
await new Promise((r) => setTimeout(r, enabled ? 6_000 : 3_000)); // load/teardown + settle
|
|
|
|
// 1. PARKED timed renders.
|
|
const parked = await page.evaluate(() => {
|
|
const v = window.__godsEyeView.viewer;
|
|
const durations = [];
|
|
for (let i = 0; i < 40; i++) {
|
|
const t0 = performance.now();
|
|
v.render();
|
|
durations.push(performance.now() - t0);
|
|
}
|
|
return durations;
|
|
});
|
|
|
|
// 2. PAN-STOP cycles: move, raise moveEnd, wait 650 ms, 20 timed renders.
|
|
const cycles = [];
|
|
for (let cycle = 0; cycle < 3; cycle++) {
|
|
const frames = await page.evaluate(async (step) => {
|
|
const v = window.__godsEyeView.viewer;
|
|
const ell = v.scene.globe.ellipsoid;
|
|
v.camera.setView({
|
|
destination: ell.cartographicToCartesian({
|
|
longitude: (-40 + step * 3) * Math.PI / 180,
|
|
latitude: 35 * Math.PI / 180,
|
|
height: 4_500_000,
|
|
}),
|
|
orientation: { heading: 0, pitch: -Math.PI / 2, roll: 0 },
|
|
});
|
|
v.camera.moveEnd.raiseEvent();
|
|
await new Promise((resolve) => setTimeout(resolve, 650));
|
|
const durations = [];
|
|
for (let i = 0; i < 20; i++) {
|
|
const t0 = performance.now();
|
|
v.render();
|
|
durations.push(performance.now() - t0);
|
|
}
|
|
return durations;
|
|
}, cycle + 1);
|
|
cycles.push(stats(frames));
|
|
}
|
|
|
|
const worst = Math.max(...cycles.map((c) => c.max));
|
|
console.log(` [${label}] parked render: ${JSON.stringify(stats(parked))}`);
|
|
console.log(` [${label}] pan-stop cycles: ${JSON.stringify(cycles)} worstFrame=${worst}`);
|
|
return { parked: stats(parked), cycles, worst };
|
|
};
|
|
|
|
const on = await measure('cables ON ', true);
|
|
const off = await measure('cables OFF', false);
|
|
console.log(`\nparked delta (ON-OFF mean): ${(on.parked.mean - off.parked.mean).toFixed(2)}ms`);
|
|
console.log(`pan-stop worst: ON ${on.worst}ms vs OFF ${off.worst}ms`);
|
|
} finally {
|
|
await browser.close();
|
|
}
|