Profiler: real-GPU breakdown by zoom, look and scene, with a baseline (t88 phase 0)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Profiler checks: headers, summaries/comparison, and unchanged pixels/simulation with clocks on."""
|
||||
import contextlib
|
||||
import io
|
||||
import math
|
||||
import copy
|
||||
from urllib.request import urlopen
|
||||
|
||||
from perf import ROOT, GPU_ARGS, quantiles, measurements, report
|
||||
from server import isolated_server
|
||||
from use_venv import ensure_playwright
|
||||
|
||||
|
||||
def main():
|
||||
q = quantiles([4, 1, 3, 2])
|
||||
assert all(math.isclose(q[k], v) for k, v in [('p50', 2.5), ('p95', 3.85), ('p99', 3.97)])
|
||||
assert dict(measurements({'calls': 10, 'total_ms': 3, 'marks_ms': {'color': 2}})) == {
|
||||
'/total_ms': 3, '/marks_ms/color': 2}
|
||||
data = {'machine': {'renderer': 'test', 'cores': 1, 'crossOriginIsolated': True, 'webgpu': True},
|
||||
'options': {'viewport': [1920, 1080], 'world': [2048, 1024]}, 'elapsed_seconds': 1,
|
||||
'scenes': {'factory': {'views': {}, 'runs': {}, 'sim': {'total_ms': 1, 'rest_ms': 0,
|
||||
'steps': {}, 'start': {'awake': 1, 'hot': 1}, 'end': {'awake': 1, 'hot': 1, 'chunks': 2}}}}}
|
||||
newer = copy.deepcopy(data)
|
||||
newer['scenes']['factory']['sim']['total_ms'] = 1.2
|
||||
out = io.StringIO()
|
||||
with contextlib.redirect_stdout(out):
|
||||
report(newer, data)
|
||||
assert '/factory/sim/total_ms: +20.0% REGRESSION' in out.getvalue()
|
||||
assert 'n/a (baseline zero)' in out.getvalue()
|
||||
ensure_playwright()
|
||||
from playwright.sync_api import sync_playwright
|
||||
with isolated_server() as url, sync_playwright() as p:
|
||||
with urlopen(url) as response:
|
||||
assert response.headers['Cross-Origin-Opener-Policy'] == 'same-origin'
|
||||
assert response.headers['Cross-Origin-Embedder-Policy'] == 'require-corp'
|
||||
response.read()
|
||||
browser = p.chromium.launch(args=GPU_ARGS)
|
||||
pg = browser.new_page(viewport={'width': 1280, 'height': 760})
|
||||
errors = []
|
||||
pg.on('pageerror', lambda e: errors.append(str(e)))
|
||||
pg.add_init_script('window.requestAnimationFrame = () => 0;')
|
||||
pg.goto(url)
|
||||
pg.add_script_tag(content=(ROOT / 'tools/perf-scenes.js').read_text())
|
||||
assert pg.evaluate('crossOriginIsolated')
|
||||
# Compare to the unwrapped functions, and hash the byte representation of all grid state.
|
||||
hashes = pg.evaluate('''() => {
|
||||
const hash = () => {
|
||||
let h = 2166136261;
|
||||
for (const a of [mat, temp, flags, stamp, part, awake, hot])
|
||||
for (const b of new Uint8Array(a.buffer, a.byteOffset, a.byteLength)) h = Math.imul(h ^ b, 16777619);
|
||||
return h >>> 0;
|
||||
};
|
||||
const results = [];
|
||||
for (const enabled of [false, true]) {
|
||||
SET.showPerf = enabled;
|
||||
generateWorld(424242, 640, 384, null);
|
||||
for (let k = 0; k < 240; k++) simTick();
|
||||
results.push(hash());
|
||||
}
|
||||
return results;
|
||||
}''')
|
||||
assert hashes[0] == hashes[1], hashes
|
||||
pg.evaluate("perfScene('factory', 1024, 640)")
|
||||
for look in ['pixel', 'smooth']:
|
||||
identical = pg.evaluate('''look => {
|
||||
perfView(look, 6);
|
||||
const now = performance.now.bind(performance);
|
||||
performance.now = () => 5000;
|
||||
R.rain = rainAt(Math.max(0, Math.min(W - 1, Math.floor(R.camX + R.bw / 2))));
|
||||
try {
|
||||
PERF_MARKS = false; drawWorld(); const a = R.canvas.toDataURL();
|
||||
PERF_MARKS = true; drawWorld(); const b = R.canvas.toDataURL();
|
||||
return a === b;
|
||||
} finally { PERF_MARKS = false; performance.now = now; }
|
||||
}''', look)
|
||||
assert identical, f'{look}: marks changed pixels'
|
||||
pg.evaluate('''() => {
|
||||
SET.showPerf = true; GAME.paused = false;
|
||||
for (let k = 0; k < 30; k++) frame(lastT + 1000 / 60);
|
||||
GAME.paused = true;
|
||||
$('cards').innerHTML = '';
|
||||
document.querySelectorAll('.toast').forEach(e => e.remove());
|
||||
}''')
|
||||
text = pg.locator('#perf').inner_text()
|
||||
assert all(word in text for word in ['world', 'light', 'overlays', 'move', 'heat', 'rest']), text
|
||||
pg.screenshot(path=f'/tmp/t88-perf-{look}.png')
|
||||
assert not errors, errors
|
||||
browser.close()
|
||||
print('PASS headers, quantiles, comparison, deterministic simulation and pixel/smooth image parity; readout screenshots saved')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user