mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-11-15 13:58:20 +00:00
Open time is one number at one instant. It cannot see the CPU Studio burns while idle, the full-document media scan every scrub frame, the same media file fetched eight times on open, or the heap kept after a project switch. This adds a browser gate for all four and the baseline they read today, before any fix. The idle window samples consecutive ten-second windows until the style-recalc count settles rather than sleeping: the first window on a media project drains the thumbnail-extraction backlog and reads 56% of a core against a flat steady state, so a fixed sleep would gate on a transient. Animation-frame scheduling is attributed by call site in every frame, which is what makes a future regression debuggable rather than merely red. The scrub window counts full-document video/audio queries during a synthetic playhead drag, patched in every frame — all of those queries happen inside the preview iframe, not the Studio document. The Chrome resolver both e2e gates need moves to a shared puppeteerEnv module.
125 lines
7.0 KiB
JSON
125 lines
7.0 KiB
JSON
{
|
|
"note": "What the build cost on the day the gate was written, before any fix landed. Every number here is a browser measurement from tests/e2e/studio-runtime-cost.mjs; none is a target. Targets live in src/lib/studioRuntimeBudgets.ts, and every window below is red against them today.",
|
|
"capturedAt": "2026-08-01",
|
|
"commit": "0ac09e1f8",
|
|
"branch": "perf/studio-real-projects",
|
|
"machine": {
|
|
"model": "Apple M4 Pro",
|
|
"os": "darwin 26.5.1",
|
|
"architecture": "arm64",
|
|
"cores": 14,
|
|
"totalMemoryBytes": 25769803776,
|
|
"browser": "Chrome/150.0.7871.24 (headless)",
|
|
"server": "Studio Vite dev server on http://localhost:5190"
|
|
},
|
|
"caveat": "The dev server is not the build users run. These numbers are a regression signal and the baseline the fixes are measured against, not a product claim.",
|
|
"runToRunVariance": "A repeat run of the fixture arm reproduced every window: idle 60.0 recalcs/s and 13.5% of a core, scrub 157 queries, open 8.38x, switch 0.38 MB per cycle. Counting assertions repeat exactly; CPU fraction, byte totals and heap slope move by a few percent.",
|
|
"arms": {
|
|
"fixture": {
|
|
"what": "Generated by tests/e2e/generateStudioLoadFixture.mjs into data/projects/ (gitignored). studio-runtime-cost-a: 133 clips, 12 tracks, 20 media sources, 140 media clips (7 clips per source). studio-runtime-cost-b: 90 clips, 15 sources, 105 media clips.",
|
|
"command": "STUDIO_URL=http://localhost:5190 bun tests/e2e/studio-runtime-cost.mjs",
|
|
"idle": {
|
|
"styleRecalcsPerWindow": [759, 600, 601, 600],
|
|
"quiescentWindowIndex": 3,
|
|
"cpuFractionOfCore": 0.1358,
|
|
"styleRecalcsPerSecond": 60,
|
|
"layoutsPerSecond": 0,
|
|
"animationFrameCallsPerSecond": 303,
|
|
"animationFrameCallsPerWindowBySite": {
|
|
"studio-document": {
|
|
"update (src/components/editor/SnapGuideOverlay.tsx:52:15)": 600,
|
|
"update (src/components/editor/useDomEditOverlayRects.ts:77:15)": 600,
|
|
"update (src/components/editor/useDomEditCompositionRect.ts:22:15)": 600,
|
|
"update (src/components/editor/offCanvasIndicatorRefresh.ts:40:13)": 600
|
|
},
|
|
"preview-iframe": {
|
|
"ia (api/runtime.js) — transportTick": 600,
|
|
"jc (api/runtime.js)": 30
|
|
}
|
|
}
|
|
},
|
|
"scrub": {
|
|
"fullDocumentMediaQueries": 157,
|
|
"perDragStep": 3.93,
|
|
"allInPreviewIframe": true
|
|
},
|
|
"open": {
|
|
"requests": 842,
|
|
"bytes": 29538065,
|
|
"mediaRequests": 65,
|
|
"distinctMediaSources": 8,
|
|
"mediaRequestsPerDistinctSource": 8.13,
|
|
"imageRequests": 15,
|
|
"distinctImageSources": 13
|
|
},
|
|
"switch": {
|
|
"cycles": 8,
|
|
"jsHeapUsedMbPerCycle": [60.26, 59.91, 60.5, 61.43, 62.53, 62.19, 62.67, 62.39],
|
|
"heapBytesPerCycle": 432052,
|
|
"nodeDriftSameProject": 35,
|
|
"listenerDriftSameProject": 9,
|
|
"documentDriftSameProject": 0
|
|
}
|
|
},
|
|
"realProject": {
|
|
"what": "eliana-montage (273 clips: 77 video, 23 audio, 263 images) alternating with biweekly-2026-07-31 (35 clips). Not in the repo; symlinked into data/projects/ for this capture. Recorded so the fixture arm can be trusted to stand in for a real project.",
|
|
"command": "STUDIO_URL=http://localhost:5190 STUDIO_RUNTIME_PROJECTS=eliana-montage,biweekly-2026-07-31 bun tests/e2e/studio-runtime-cost.mjs",
|
|
"idle": {
|
|
"styleRecalcsPerWindow": [1085, 1112, 1118],
|
|
"firstWindowLayouts": 129,
|
|
"quiescentWindowIndex": 2,
|
|
"cpuFractionOfCore": 0.2713,
|
|
"styleRecalcsPerSecond": 111.8,
|
|
"layoutsPerSecond": 0,
|
|
"animationFrameCallsPerSecond": 338.2,
|
|
"animationFrameCallsPerWindowBySite": {
|
|
"studio-document": {
|
|
"update (src/components/editor/SnapGuideOverlay.tsx:52:15)": 559,
|
|
"update (src/components/editor/useDomEditOverlayRects.ts:77:15)": 559,
|
|
"update (src/components/editor/useDomEditCompositionRect.ts:22:15)": 559,
|
|
"update (src/components/editor/offCanvasIndicatorRefresh.ts:40:13)": 559
|
|
},
|
|
"preview-iframe": {
|
|
"ia (api/runtime.js) — transportTick": 559,
|
|
"Al (gsap.min.js) — GSAP ticker": 559,
|
|
"jc (api/runtime.js)": 28
|
|
}
|
|
}
|
|
},
|
|
"scrub": {
|
|
"fullDocumentMediaQueries": 124,
|
|
"perDragStep": 3.1,
|
|
"allInPreviewIframe": true
|
|
},
|
|
"open": {
|
|
"requests": 1771,
|
|
"bytes": 233769675,
|
|
"mediaRequests": 435,
|
|
"distinctMediaSources": 79,
|
|
"mediaRequestsPerDistinctSource": 5.51,
|
|
"imageRequests": 529,
|
|
"distinctImageSources": 264
|
|
},
|
|
"switch": {
|
|
"cycles": 8,
|
|
"jsHeapUsedMbPerCycle": [73.02, 73.94, 94.14, 74.79, 76.93, 75.38, 74.84, 75.73],
|
|
"heapBytesPerCycle": 314008,
|
|
"nodeDriftSameProject": 40,
|
|
"listenerDriftSameProject": 9,
|
|
"documentDriftSameProject": 1
|
|
}
|
|
}
|
|
},
|
|
"agreementWithTheProblemFrame": {
|
|
"idleBacklogThenSteadyState": "Reproduced. The real project's first window carries 129 layouts and 56% of a core; every window after it has ZERO layouts and a flat recalc count. A fixed sleep would have gated on the first window.",
|
|
"idleStyleRecalcRate": "Reproduced: 111.8/s measured against 120/s in the Problem Frame — two per frame at 60fps.",
|
|
"idleCpu": "27.1% of a core measured against 16-17% in the Problem Frame. Same order, not the same number: this capture is headless Chrome against a Vite dev server. The deterministic counts agree; the CPU fraction is environment-sensitive, which is why the gate carries a constrained tier.",
|
|
"idleCallSites": "Reproduced exactly: SnapGuideOverlay, useDomEditOverlayRects, useDomEditCompositionRect, offCanvasIndicatorRefresh in the Studio document, plus transportTick and the GSAP ticker inside the preview iframe.",
|
|
"scrub": "Every full-document media query happens inside the preview iframe; the Studio document issues none. Roughly three to four per drag step.",
|
|
"openAmplification": "Reproduced: 79 distinct media sources and 264 distinct images on the real project, matching the Problem Frame's 79 and 263. The request ratio measured 5.5x against 4.3x reported.",
|
|
"openBytes": "233.8 MB measured against 534.6 MB reported. This gate sums CDP encodedDataLength — bytes actually moved over the wire — so requests served from the browser cache contribute nothing. The request COUNT (1,771 against 1,737) agrees closely, so the difference is accounting, not behaviour.",
|
|
"switchRetention": "Reproduced: monotonic heap growth of 0.31 MB per cycle on the real project and 0.43 MB on the fixture, against ~0.5 MB reported, with nodes, listeners and documents flat."
|
|
},
|
|
"verdictToday": "All four windows fail. idle CPU 13.6% vs 1% budget; idle recalcs 60/s vs 5/s; idle animation-frame calls 303/s vs 5/s; scrub 157 full-document media queries vs 0; open 8.13x per distinct media source vs 1.2x; switch 0.41 MB per cycle vs 0.10 MB."
|
|
}
|