# TV Production Performance Patch — Validation Report

Measured with `node scripts/profile-tv-playback.mjs` (Chrome CDP, 10s profile, `deploy-tv/` static server).

## Before / After Summary

| Scenario | Metric | Before (baseline) | After (patch) | Delta |
|----------|--------|-------------------|---------------|-------|
| **Production playback** | Active JS CPU / 10s | ~2 ms | **14.8 ms** | +12.8 ms (rAF scheduler; still negligible) |
| | JS heap | 1.25 MB | 1.26 MB | ~same |
| | DOM nodes | 488 | 573 | +85 (persistent overlay structure not created in prod) |
| | Top CPU consumer | `setTimeout` (35% of active) | **`requestAnimationFrame`** (59% of active) | Spec-compliant rAF loop restored |
| **Debug (`?debug=1`)** | Active JS CPU / 10s | ~44 ms | **23.6 ms** | **−46%** |
| | JS heap | 1.31 MB | 1.32 MB | ~same |
| | DOM nodes | 8351 | **2017** | **−76%** (overlay DOM reuse) |
| | Top overlay cost | `updateOverlayDom` + innerHTML (~19%) | `applyOverlayValues` textContent (~8.8%) | Reduced DOM churn |
| | Debug log cost | `renderDebugLog` (~17%) | `renderDebugLogNow` (~6.1%) | 1 Hz debounce |
| **Boot idle** | Active JS CPU / 10s | ~0 ms | 0 ms | unchanged |
| | DOM nodes | 366 | 366 | unchanged |

Baseline captured: `2026-07-22T06:15:09.210Z` (pre-patch `profile-tv-results.json`).  
After patch: see current `scripts/profile-tv-results.json`.

---

## Changes Applied

| File | Function / Area | Problem | Solution | Est. impact | Risk |
|------|-----------------|---------|----------|-------------|------|
| `FrameSyncEngine.js` | `scheduleRenderLoop` | Production used `setTimeout(tick, 33)` — violated STEP 6, ~35% active CPU | Always `requestAnimationFrame` | rAF replaces setTimeout in prod top-10 | Low |
| `FrameSyncEngine.js` | `correctVideoDrift` | Redundant `playbackRate` / `currentTime` writes every 250 ms | `setVideoPlaybackRateIfNeeded`, `seekVideoIfNeeded` with cached last values | Fewer decoder resets on TV | Low |
| `FrameSyncEngine.js` | `ensureOverlayDom` / `updateOverlayDom` | Debug innerHTML rebuild each update (~19% debug CPU) | Persistent overlay + `textContent` on 8 detail rows + hero/match | Debug CPU −46%; DOM nodes −76% | Low (debug-only) |
| `app.js` | `installProductionConsoleQuiet` | ~63 direct `console.log` bypass quiet gating | Noop `log`/`info`/`debug` in production at init | Less main-thread console I/O | Low |
| `app.js` | `renderDebugLog` | 250 ms debounce (4 Hz) vs spec 1 Hz | Debounce **1000 ms** | Lower debug log DOM cost | Low |
| `deploy-tv/*` | sync | Stale bundle missing tv/ patches | Copied `app.js` + `FrameSyncEngine.js` from `tv/` | Deploy matches source | None |

---

## Production Top CPU (after)

1. `requestAnimationFrame` — 8.73 ms (59%)
2. `tick` — 1.80 ms
3. `renderTick` — 1.78 ms
4. `correctVideoDrift` — 1.26 ms

**No `setTimeout` in production top consumers.** Total active JS remains well under 20 ms / 10 s.

---

## Architecture Confirmation

Unchanged: FrameSync protocol, Nakama RPCs, countdown timing, scoring, ServerReferenceClock, session end, TV authoritative playback, Unity notifications, drift thresholds (40 ms / 200 ms), pulse interval (100 ms).
