Skip to content

perf(producer): size a chunk's capture browsers by its frame cost, not its frame count - #6319

Merged
miguel-heygen merged 1 commit into
mainfrom
perf/chunk-workers-by-cost
Oct 25, 2026
Merged

miguel-heygen merged 1 commit into
mainfrom
perf/chunk-workers-by-cost

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

What

A chunk's capture browser count now follows its estimated capture cost, not its raw frame count. Each chunk slice carries captureCost (mean frame cost over the plan's cheapest frame, from the same weights the cost-weighted cut uses). effectiveChunkFrames turns frames into cost-scaled frames once, and both calculateOptimalWorkers and resolveChunkCaptureWorkers read that one number.

Why

The cost-weighted cut (#6295) makes the chunks over a video-heavy stretch short, and worker sizing gives a browser per 20-30 raw frames. Chunks of 28-59 frames over the heavy stretch ran with 1-2 browsers while the other chunks ran 3, so the busiest frames were captured at a third of the throughput on a function billed for all of its memory. On the 4K Lambda fixture, per-chunk logs across 5 same-hour 0.8.197 vs 0.8.198 pairs:

Chunk (0.8.198) Frames Browsers Mean wall
2, 3, 4 38, 28, 28 1 36-40 s
5 59 2 34 s
others 75 3 ~22 s

The sum of chunk wall rose 556.7 s -> 576.9 s (+3.6%) while the slowest chunk fell 59 s -> 45 s.

How

  • ChunkSliceJson.captureCost (optional, absent when 1) is stamped by withChunkCaptureCost in buildPlanChunkSlices, so it applies to every plan cut, and read back by parseChunkSlices (validated finite and above 1).
  • renderChunk sizes workers from effectiveChunkFrames(framesInChunk, slice.captureCost).
  • Light chunks and plans without video windows carry no captureCost, so their sizing is unchanged.

Test plan

  • resolveChunkCaptureWorkers: a 28-frame chunk at 3.6x cost gets 3 browsers (1 at its raw frame count); a light 75-frame chunk is unchanged.
  • chunkWeights: a costly window's chunks are stamped, light chunks are not, and a short costly chunk is sized like the longer light chunks beside it.
  • Both new tests go red when effectiveChunkFrames returns the raw frame count. oxlint and oxfmt clean.
  • Not covered by a test: the renderChunk call site itself; it is checked by the Lambda run below.
  • Lambda: 5 same-hour interleaved pairs (alternating order), stock main vs this branch, H.264 4K fixture, default flags, 22 chunks:
Pair Cost stock -> branch Wall (s) Slowest chunk (s)
1 $0.0808 -> $0.0736 (-8.9%) 56.0 -> 53.4 46.7 -> 29.7
2 $0.0744 -> $0.0738 (-0.8%) 43.9 -> 46.1 35.5 -> 38.0
3 $0.0748 -> $0.0698 (-6.7%) 43.6 -> 40.1 35.4 -> 29.7
4 $0.0750 -> $0.0732 (-2.4%) 43.1 -> 39.1 35.0 -> 30.5
5 $0.0747 -> $0.0726 (-2.8%) 43.3 -> 39.1 34.9 -> 30.1

Mean cost -4.3% (95% CI -8.5% to -0.2%), median $0.0748 -> $0.0732; median wall 43.6 -> 40.1 s (-8%). Cost never rose by more than the run-to-run spread of the stock side.

Limits

  • captureCost comes from the video-pixel weights, so heavy page content without video is not counted (same limit as the cut).
  • The 1-worker floor for chunks under 60 raw frames still applies to chunks with no captureCost.

Size

The producer package grows by 746 B packed (stock main 773,896 -> 774,642 by npm pack), inside the budget's 1% tolerance on current main, so scripts/package-size-budgets.json is untouched.

@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 · 2 nits · head 176d0e4b

  • nit: Comments (comment-ratchet) is red. The comment share rose in chunkWeights.ts (9/109 vs 7/90) and freezePlan.ts (99/429 vs 98/427). The check is not required; trimming a doc line in each file fixes it.
  • nit: the body's Lambda section still reads "Table to follow". Please fill it in before merge so the cost claim has its numbers.
Scope

I read the full diff (7 files). Checks I made:

  • Weights are floored at PAGE_BASE_WEIGHT 0.7, so lightest is never 0 and the cost can't be NaN or Infinity, which parseChunkSlices would reject.
  • A captureCost of 1.00 after rounding is left unstamped, which matches the parser's > 1 check.
  • Older readers ignore the extra key, and plans without it size chunks as before.
  • If cost inflates the worker count past the frame count, distributeFrames drops the empty ranges, and maxCaptureWorkers still caps the count.

chunkWeights.test.ts (20 tests) and resolveChunkCaptureWorkers (5 tests) pass locally. No prior reviews.

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 126 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)

Unstable (3)

  • seqplainkeys-none-px-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true
  • seqplainkeys-none-px-r0-nested-z100: tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true
  • seqplainkeys-none-pct-r0-nested-z100: tracking 0.05, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo false, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport true

@miguel-heygen
miguel-heygen force-pushed the perf/chunk-workers-by-cost branch from 176d0e4 to b8f493c Compare October 25, 2026 15:47

@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 — 1 resolved, 1 open, 0 new · 176d0e4 → b8f493c

The rebase onto main plus three trimmed doc comments clears Comments; the code is unchanged. Still open: the body's Lambda section reads "Table to follow".

@miguel-heygen
miguel-heygen force-pushed the perf/chunk-workers-by-cost branch from b8f493c to 6252086 Compare October 25, 2026 16:13

@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 — 2 resolved, 0 open, 0 new · b8f493c → 6252086

The PR patch is unchanged apart from the +746 B packed-size budget for @hyperframes/producer. The Lambda pair table is now in the body. The rest of the diff since the last head comes from the rebase onto main (#6314).

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 25, 2026
@miguel-heygen
miguel-heygen force-pushed the perf/chunk-workers-by-cost branch from 6252086 to ab6c72b Compare October 25, 2026 18:34

@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 open, 0 new · 6252086 → ab6c72b

This is the rebase onto main. The PR patch is the same as the one I approved at b8f493ca; the size-budget bump is dropped. All Actions runs on this head are green.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 69405a7 Oct 25, 2026
75 checks passed
@miguel-heygen
miguel-heygen deleted the perf/chunk-workers-by-cost branch October 25, 2026 19:32
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