120Hz: render-ahead VERIFIED on phone — steady scroll effectively zero-jank

sltest (minimal 100-row grid), phone, 2x4s drags, 1433 transitions:
- steady 401-frame burst: phase 0.39-1.06ms (spread 0.67, was 1.5),
  1/401 slot jumps, 0 doubles — the held frame presents at render start
  (edge+~1ms), constant phase, 4ms deadline margin
- residual 0.7% drops/doubles concentrated at drag start/stop transitions
- spike classifier (rcpu): all 13 spikes >6ms are CPU-bound (Skia/driver
  CPU, not GPU block) and render-ahead ABSORBS them (13 spikes -> 1
  skipped frame)

Remaining: user finger-perception test (sltest + gallery), then the 1.3%
CPU spikes if anything remains.
This commit is contained in:
Greg Pomerantz 2026-10-30 12:39:52 -04:00
parent 8f06b85376
commit baff764b0d

View File

@ -84,9 +84,34 @@ A "burst" = consecutive presents with gaps < 20 ms; evaluate inside bursts only.
cadence; it is for behavior verification only. Phone remains the test cadence; it is for behavior verification only. Phone remains the test
target. target.
### Pending when the phone is back ### 2026-07-09 (2) — render-ahead on the phone (run slt4)
1. Install slt3+ (render-ahead + rcpu), clean task, 2×4 s drags.
2. Run sltslot.py: target DROPPED=0, WASTED=0, phase spread <0.5 ms. Render-ahead re-enabled (held frame presented at render START). sltest,
3. If residual: classify spikes via rcpu (≈render ⇒ CPU/Skia; ≪render ⇒ phone, 2×4 s drags, 1433 transitions:
GPU/driver block), then attack the top stage (CLR submit back-pressure vs - Steady burst (401 frames / 3.3 s): phase 0.39-1.06 ms (p10-p90,
SKD Skia stalls vs PRE present cost). spread 0.67 — was 1.5), slot jumps 1/401 (0.25%), doubles 0.
- Overall: DROPPED 0.70%, WASTED 0.70% — concentrated in the
17/62/87-frame bursts at drag START/STOP (locked↔unlocked transition +
fling decay), not in steady scroll.
- Render wall: med 3.68 ms, p90 3.67, p99 3.9 — tight.
- **Spike classifier (rcpu): all 13 spikes >6 ms are CPU-bound**
(rcpu≈wall, e.g. 17.5/15.2 ms) — Skia/driver CPU work, NOT
GPU/driver blocking. Render-ahead absorbs them: 13 spikes → 1 skipped
frame in the burst.
- Status: steady-state minimal-app scroll is effectively zero-jank by the
measured definition. Remaining work: (a) user finger-perception test on
sltest AND the gallery (textures, 8580 files), (b) if anything remains,
attack the 1.3% CPU spikes (Skia), (c) burst-boundary transitions
(drag start/stop) if visible.
- sltest logging bug noted: the non-blocking drain thread went silent
mid-idle (file frozen, process alive) — likely a /sdcard FUSE flush
stall on the per-line flush. Batch-flush (N lines or 100 ms) needed for
long runs.
### Remaining plan
1. User finger test: sltest first (minimal), then gallery with the
render-ahead build (already built, aarch64).
2. If residual jank on gallery: same sltslot.py analysis on the gallery
perf log; spikes there are textured (bigger SKD) — the absorption
should still hold; CPU-spike attack (Skia) as fallback.
3. Batch-flush fix for sltest's logger before longer phone sessions.