Skip to content

fix(producer): --workers N is a ceiling, drawElement renders keep their single worker - #6314

Merged
miguel-heygen merged 2 commits into
mainfrom
checklong/workers-ceiling
Oct 25, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
checklong/workers-ceiling

Conversation

@miguel-heygen

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

Copy link
Copy Markdown
Collaborator

What

An explicit --workers N no longer skips the single-worker drawElement choice. N is a ceiling: a render that drawElement can capture still uses one worker; any other render uses up to N screenshot workers.

Why

--workers N (a memory cap, for example from an app that sets one) pushed an otherwise drawElement-eligible long render onto N screenshot workers, which is the slower path: on a 60 s 1080p30 video the same render took 41.4 s with --workers 3 against 35 s on auto, and used more memory.

Related work

None open.

How

shouldPreferSingleWorkerDrawElement no longer takes the requested worker count, so the exemption for an explicit number is gone. The parallel-router predicate keeps its own exemption (an explicit count never routes to three drawElement workers, which could exceed the ceiling). The log line and the --workers row in the CLI reference say N is a ceiling.

Test plan

  • Unit: the predicate inverts for every multi-worker count (2, 3, 4, 24) and leaves a one-worker render alone; renderOrchestrator.test.ts passes (285 tests); lint, format and typecheck clean.

  • The call-site change cannot be reached by a unit test without running a real render, so the before/after is a real render below.

  • Unit tests added/updated

  • Manual testing performed (see below)

  • Documentation updated (if applicable)

  • Comments follow CONTRIBUTING.md "Comments": they say why, not what, and a bug fix says what the code must do and how to reproduce the bug

Measured

60 s 1080p30 video fixture (1,800 frames), laptop with 18 cores, --workers 3, three alternating before/after pairs with the machine busy (load average 12 to 14). Before is the released CLI; after is the same release with only the exemption removed.

wall peak memory (whole process tree)
before (3 screenshot workers) 43.2 s, 48.5 s, 42.4 s 2.45 to 2.48 GB
after (single drawElement worker) 48.8 s, 55.3 s, 38.0 s 2.08 to 2.11 GB

On a fixture this short the wall time is a wash within the noise (single drawElement alone ran 34.6 to 40.8 s on a quiet machine; three screenshot workers 41 s, four 33 s). What the change guarantees is the same path and the same memory as auto: --workers 4 drops from 3.1 to 2.1 GB. The earlier benchmark behind the inversion measured the gain on longer renders (2,380 frames: 66 s single against 109 to 127 s at 2 to 5 screenshot workers).

@mintlify

mintlify Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Oct 25, 2026, 2:49 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

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

  • seqplainkeys-none-center-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

@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 · 1 nit · head d64a6181 (re-pinned from 05201ce1; the only change since is the doc comment)

An explicit N still pins the parallel router off (requestedWorkers stays on shouldPreferParallelDrawElement), and the self-verify retry falls back to preRoutingWorkerCount, which is N. So N stays a true ceiling on both paths.

  • nit · renderOrchestrator.ts:2182: the experimentalParallelDeOptIn doc still says "honor it like an explicit --workers request". An explicit N no longer exempts a render from this predicate, so the line now says the opposite. Suggested wording: "— keep the parallelism it asked for."
Scope and CI

I read the predicate, both call sites, the calibration gate, the routing block and the docs row. CI on 05201ce1 failed the producer packed-size budget by 23 bytes; d64a6181 passes Build. On d64a6181, Build, Typecheck, Lint, Producer unit and integration tests, regression and Windows render all pass. CI then shows Test failed because Test (runtime) was cancelled, and that shard does not cover this diff. It still needs a green re-run before merge.

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 26e3045 Oct 25, 2026
113 of 115 checks passed
@miguel-heygen
miguel-heygen deleted the checklong/workers-ceiling branch October 25, 2026 15:53
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