Skip to content

Chrome captures: pixel, DPR and break captures take 8 cases at once (same bytes) - #162

Merged
thejackshelton merged 42 commits into
masterfrom
chrome-capture-parallel
Oct 5, 2026
Merged

thejackshelton merged 42 commits into
masterfrom
chrome-capture-parallel

Conversation

@thejackshelton

Copy link
Copy Markdown
Contributor

What changed (packages/parity)

  • New src/chrome-pool.ts:
    • CHROME_PAGES is one per core, at most 8.
    • inOrder(items, width, f) runs at most width items at a time and returns results in item order.
    • On a failure it starts nothing new, lets every started item end (so no page is mid-capture when the browser closes), and then throws the first failure in item order.
    • It is a leaf module, so the capture steps' regen inputs do not grow.
  • cli/pixel-capture.ts, cli/dpr-capture.ts and cli/break-capture.ts take CHROME_PAGES cases at once in each DPR launch (research Parity: shard the determinism check per fixture #5 in speed-research.md §2.3).
    • Each case already had its own browser context (openPage or captureFixture), so cases share no state.
    • The zoom guard still runs before and after each launch, and the software-raster precondition is unchanged.
    • The pixel manifest keeps case order. Break captures are keyed by case, so finishing order changes nothing.
    • --recheck uses the same pool.

Tests

  • New test/chrome-pool.test.ts: the most items running at once is exactly width; results come back in item order whatever order they finish in; the first failure in item order is thrown only after every started item ends; nothing starts after a failure; a bad width is refused.

What passed

  • pnpm typecheck: pass.
  • vitest run packages/parity/test/chrome-pool.test.ts: 2 passed.
  • pnpm regen on the branch (job regen-speed-capture-regen): dpr-capture, break-capture and pixel-capture ran. Fixed point after 1 pass, 0 files changed, git status clean. Every PNG, DPR capture and break capture is byte-identical.

The Chrome loops per DPR, from the steps' own logs. Before is two earlier local regens (mq-r0, c2); after is this branch's regen. Both were under load.

loop before (s per DPR) after (s per DPR)
pixel-capture 35–51 17–33
dpr-capture 28–39 16–20
break-capture 26–36 11–12

The rest of each step's time is its fixture compiles, which #151 (native hash) cuts about 6×.

Note

The text stack (TXT1a and the later PRs on it) adds an authoredPrepare line inside these same loops, so it will need a small merge resolution when it catches up. The PM chose to take that cost now.

No tolerance, check, test or fixture changed.

🤖 Generated with Claude Code

thejackshelton and others added 30 commits October 4, 2026 20:47
…ules, so ua:capture's regen inputs leave out the compiler
…ault)

planted-swift.test.ts and planted-kotlin.test.ts compiled and ran a planted harness for each of the 7 FAULTS in one test
(planted-swift took 734 s on the CI runner, planted-kotlin 329 s). Each (target, fault) pair is now its own test file
(planted.ts holds the shared test), so vitest schedules them across workers and shards. planted-union.test.ts proves the
files cover FAULTS on both targets exactly once.
The determinism describe of parity.test.ts (356 tests, 290 s of its 548 s on the CI runner) runs from
parity-determinism-<k>.test.ts, one chunk of FIXTURES per file under the same describe titles, each with its own Chrome and
its own coverage check. parity.test.ts keeps a coverage test proving the chunk files together check every fixture once.
… with any NaN; corpus inputs, results and digests write every NaN as 7ff8000000000000 (x86-64 makes some fff8...)
… are not serialized through Playwright's value serializer
The quiet gate required zero other heavy-slot holders and load under 20. A near-idle holder (a profiling run) kept the gate
shut at load ~1 while a batch's single failing file waited to be rerun. Below load 6 the machine counts as quiet regardless
of holders; the quiet request still stops new jobs from starting. land.test pins both sides.
digest: SHA-256 through Node's native hash when available (8x faster compiles, same digests)
regen: ua:capture's inputs leave out the compiler (platform.ts imports the reference platforms from their own modules)
SLOW-SPLIT 1: planted translator fault tests, one file per (target, fault)
…publish, never returned without it (the landing driver's ignored-file cleanup leaves such entries)
…utputs

packages/translate/out/{kotlin,swift}/ are content-keyed caches valid for any tree. #155's clean removed their files but not
their directories, which left stale entries that blocked every later build of the key (fixed at the source in #164); keeping
them also saves the harness rebuilds on every proof. land.test adds both to the kept set.
…try root cause), where each target stopped
thejackshelton and others added 12 commits October 5, 2026 01:08
translate: a stale harness cache entry (artifact deleted, directory kept) is replaced, never returned; root cause of the land-147 'Unable to access jarfile' failures
land: keep the translate harness build caches when cleaning ignored outputs
land: an idle machine is quiet even with a heavy slot held
SLOW-SPLIT 2: parity determinism shards in 4 chunk files
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