perf: parallel viewports + parallel checks + console dedup#115
Merged
Conversation
Building on 0.11.14's parallel-sides change: - Wrap the outer `for (const viewport of viewports)` in runWithConcurrency, default 2. The standard mobile+desktop set now runs fully concurrent — 4 BrowserContexts simultaneously (mobile/prod + mobile/cand + desktop/prod + desktop/cand). Each viewport still runs its two sides in parallel via runOneSide. Expected ~40% additional collect speedup on top of 0.11.14. - New `--max-viewport-concurrency <n>` flag (default 2). Memory- constrained machines can set 1 to revert to serial-viewport behavior; runs with a 3rd viewport (e.g. tablet) can cap how many run at once. - Add a process-global semaphore in src/llm/client.ts capping concurrent LLM calls to 3. With 4 sides × recovery budget 3 in flight at peak, we could push 8-12 simultaneous LLM calls — past Anthropic tier-1's 4 RPS. Calls now queue instead of blowing up with 429s. Default 3 leaves headroom for the post- collect aggregate call to fire during peak concurrency. Same `runOneSide` from 0.11.14 is now wrapped in `runOneViewport` which Promise.all's the two sides; runWithConcurrency drives the top level. Merge into allFlowCaptures/allPageCaptures still runs single-threaded after each viewport's await resolves, so no race on the shared accumulators or learned-selectors promotion. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two changes that close the loop on user feedback after a 25m46s run: 1) `runAllChecks` ran ~27 checks sequentially (`for ... await check`), spending ~4m26s on a phase whose dominant cost is the slowest single check. Almost every check is a pure CPU aggregation over PageCapture data (string diffs, regex matches, console filtering); the 3 network-bound ones (seo-deep-audit, footer-links-health, plp-pagination) are I/O-bound and parallelize cleanly. Now uses Promise.all — phase wall-clock collapses to the longest single check (~30-60s expected on bagaggio). 2) consoleErrorsBaseline emitted one Issue per (page × error) pair, so the same domain-key mismatch leaking across home/search/etc produced 4-5 duplicate "Top issues" entries. Refactored to group by normalized error key across all page pairs and emit ONE issue per unique error with the affected-pages list inline. Direct response to user feedback: "console log não deveria ter um teste pra ele … fazer o dedup e descrever quais paginas tiveram aquele error". The schema-level Issue shape is unchanged. Added test: dedupes the same error across pages into one issue. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
c4e733c to
f96e759
Compare
Observed on CI main run 27668261636: `setTimeout(r, 20)` returned at 19.99ms — below the test's `toBeGreaterThanOrEqual(20)` threshold. Timer scheduling on busy GitHub Actions runners can fire ~1-3ms early even when a 20ms timer was requested. Bumping the sleep to 30ms and the threshold to 25ms keeps the "totalMs forgot to accumulate" check strict while tolerating realistic scheduler jitter. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Combines what would have been PRs #2 and #3 of the performance plan (their stacked-on-#113 branches got auto-closed when #113 squash-merged). Bundles cleanly because all changes are independent within the file scope.
Parallel viewports + LLM semaphore (was #114):
runWithConcurrencysomobile,desktopcollects fully parallel — 4 BrowserContexts simultaneously (mobile/prod, mobile/cand, desktop/prod, desktop/cand)--max-viewport-concurrency <n>flag (default 2) for memory-constrained machines or runs with >2 viewportssrc/llm/client.ts(3 slots) so 4 sides × recovery budget 3 calls never exceed Anthropic tier-1's 4 RPSParallel checks + cross-page console dedup (was #115):
runAllChecksran ~27 checks sequentially (~4m26s). Almost all are pure CPU aggregations + 3 are I/O-bound — all parallelize cleanly.Promise.allnow collapses the phase to the slowest single check (~30-60s expected).consoleErrorsBaselinewas emitting one Issue per (page × error), crowding the report with 4–5 duplicates of the same domain-key mismatch. Now groups by normalized error key across all page pairs and emits ONE issue with the affected-pages list inline (direct response to user feedback). Added a test for the new behavior.Bumps to 0.11.16. After this PR merges on top of 0.11.14: expected total run wall-clock ~6-8min on bagaggio (down from 25m46s baseline — hitting the plan's goal).
Test plan
bun run checkcleanbun run lintcleanbun run test— 702/702 passchecksphase < 1min, console errors grouped🤖 Generated with Claude Code