Skip to content

perf(core): a film opens and seeks without pre-styling every hidden scene, cuts stay smooth - #6356

Merged
miguel-heygen merged 2 commits into
mainfrom
dslivers/clip-warm-on-play
Oct 26, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
dslivers/clip-warm-on-play

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

What

#6189 gives each clip the visibility pass hides its first visible style pass once, on the next seek, so a cut frame does not pay it. That pass also ran at open and after every mount, including far scenes a scrub only passes over. This change runs it only while playing, for clips whose start is within the 2 s lookahead: the scene about to be cut into gets it 1-2 s before its cut, and open, seeks and scrubs skip it.

packages/core/src/runtime/init.ts: styleClipsDueVisibleOnce(t) replaces styleHiddenClipsVisibleOnce(); a hidden clip waits in the set until playing brings its start within the lookahead, and leaves it once styled, shown, or past its start.

Measurements

Software-rendered machine (shared Linux box, 8 cores, SwiftShader, headless Chrome 152). 3 runs per cell, alternating columns. Columns: main before #6189 (26e3045), #6189's head (80e934a, measured with its runtime d4ff3fc), and this change. Load is the 1-minute load during each table's runs.

Play and scrub, 23-minute film. Open: play 6 s from the start right after the page is ready, then scrub ahead from 700 s at 2 s of film per frame for 5 s. After a seek: the same, after a seek to 4 s before the cut at 633.9 s. Warm: seek 2 s past that cut and settle, scrub ahead from 300 s, then play from 4 s before the cut.

fps (3 runs) main #6189 this change load
Open: play 12.5, 16.0, 16.1 16.9, 17.5, 16.3 16.9, 17.2, 16.0 2.4-7.5
Open: scrub 4.5, 4.6, 5.3 7.0, 7.2, 6.4 7.0, 7.1, 6.7 2.4-7.5
After a seek: play 6.7, 7.8, 9.5 12.8, 14.2, 14.5 12.3, 15.1, 14.7 4.3-10.5
After a seek: scrub 5.1, 5.2, 5.9 6.4, 6.7, 7.2 6.5, 7.4, 7.0 4.3-10.5
Warm: play 5.8, 5.7, 5.3 14.8, 15.1, 14.7 14.6, 15.3, 15.7 2.5-6.4
Warm: scrub 7.9, 8.0, 7.8 8.2, 8.3, 8.2 8.5, 8.4, 8.7 2.5-6.4

Open and the first seek. A fresh browser opens the film, waits for ready and 3 s, then seeks once and waits for the seek to complete and two frames.

ms (3 runs) main #6189 this change load
23-minute film: first seek to 700 s 442, 335, 317 415, 393, 457 469, 327, 341 6.3-9.3
23-minute film: first seek to 20 s 79, 83, 94 45, 46, 42 42, 42, 34 6.3-9.3
50-second 3840x2160 film: open to ready 13227, 4562, 4528 8355, 4975, 5013 7423, 4105, 4373 1.0-8.6

Cut frames. The main-thread task of the first frame whose film time passes each scene start, during play from about 0.5 s before it. Main against this change.

50-second film (load 2.5-15.9) main (ms) this change (ms) medians, change minus main
17.46 s 63, 164, 67 50, 61, 48 -17
23.17 s 104, 102, 102 57, 4, 56 -46
30.5 s 114, 110, 111 96, 103, 107 -8
40.04 s 103, 72, 75 36, 43, 599 -32
45.0 s 122, 87, 109 81, 88, 82 -27
23-minute film (load 4.7-9.3) main (ms) this change (ms) medians, change minus main
14.6 s 53, 72, 133 22, 28, 35 -44
23.0 s 80, 84, 32 63, 73, 204 -6
616.5 s 104, 93, 219 117, 78, 86 -18
633.9 s 92, 88, 146 80, 158, 82 -10
646.5 s 126, 119, 121 100, 25, 92 -29

Unconfirmed: the 599 ms run at 40.04 s (load 7.7) is one run of three; a low-load re-run of that cut is pending. Several cells ran above load 6; they are re-run at lower load as the machine allows.

Tests

  • init.test.ts: a hidden clip, its far scene included, is styled visible once while playing toward its start, not while paused and not before its start is within the lookahead. It fails with each of these removed, one at a time: the pass itself, the playing check (styled while paused), the lookahead bound (styled 4 s early), the far-scene unlock.
  • On the Linux box, on perf(core): the preview mounts and draws only the scenes near the playhead #6189's head plus this change: the touched test files (init.test.ts, init.swapScenes.test.ts, timedClipHide.test.ts, farScenes.test.ts; 432 passed), the new test 3 runs in a row, the core typecheck and the formatter. The same run on this branch's base is in progress.

@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 186 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head e9106cc1

The pass now runs only while playing, for hidden clips whose start is within LOOKAHEAD_SECONDS, with the same start resolver dueSoon uses. Clips that are shown, disconnected, or already past their start leave the set without a pass, so the set stays small. CI, Player perf and regression are green. Player Safari perf was still running at review time.

Scope

Read styleClipsDueVisibleOnce and its only call site (seekRootChildrenAndAdapters), the add site in the visibility pass (clipsNeverStyledVisible.add), dueSoon/LOOKAHEAD_SECONDS (declared after the closure but only read at call time, so no TDZ), and the updated init.test.ts case. By design, paused seeks, scrubs and render-mode seeks skip the pass. Perf tables taken as reported.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 6bc0b68 Oct 26, 2026
82 checks passed
@miguel-heygen
miguel-heygen deleted the dslivers/clip-warm-on-play branch October 26, 2026 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant