perf(coverage): reduce RPC data and unnecessary serializations - #10781
Merged
sheremet-va merged 1 commit intoJul 23, 2026
Conversation
AriPerkkio
commented
Jul 15, 2026
AriPerkkio
left a comment
Member
Author
There was a problem hiding this comment.
At the moment this PR is 100% Fable-slop - I took quick look at the changes and they'll need some adjusting. And testing of course. Opening draft PR for visibility at this point.
✅ Deploy Preview for vitest-dev ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
@vitest/browser
@vitest/browser-playwright
@vitest/browser-preview
@vitest/coverage-istanbul
@vitest/coverage-v8
@vitest/expect
@vitest/mocker
@vitest/pretty-format
@vitest/snapshot
@vitest/spy
@vitest/ui
@vitest/utils
vitest
@vitest/web-worker
commit: |
|
📝 Ran ecosystem CI: Open
|
|
📝 Ran ecosystem CI: Open
|
AriPerkkio
force-pushed
the
perf/coverage-serialization
branch
2 times, most recently
from
July 23, 2026 07:01
b7e2ad6 to
06660ba
Compare
AriPerkkio
force-pushed
the
perf/coverage-serialization
branch
from
July 23, 2026 07:10
06660ba to
3684f15
Compare
AriPerkkio
marked this pull request as ready for review
July 23, 2026 07:21
AriPerkkio
requested review from
hi-ogawa and
sheremet-va
and removed request for
hi-ogawa
July 23, 2026 07:21
sheremet-va
approved these changes
Jul 23, 2026
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Description
Adds two performance improvements I've had in mind long time:
Currently we are sending coverage JSON data from Node side workers to main thread, and then writing that to file system. Now we'll write the data directly in the worker and just pass the path to main thread. Initially I thought writing in workers would be worse, but it should actually be faster. RPC always requires serialization that's costly.
When reviewing fix(browser): disable client
cdpAPI whenallowWrite/allowExec: false#10444 I realized browser mode v8 coverage is doing unnecessary RPC hops:Now we'll instead just write the results to file system in the first call, and never pass the V8 script coverage to browser.
LLM Generated analysis of perf changes
Prompted Claude to run
vitest-coverage-largelocally withmainand this PR. There's noticeable perf change inbrowser + v8, as now we don't bounce the results unnecessary over the WS RPC. 🔥LLM Generated sequence diagrams before-after
Output of following prompt below.
Details
How coverage results move between processes
Node pools (
threads,forks,vmThreads,vmForks)Before — full results cross the worker↔main boundary and are serialized twice more on the main process:
sequenceDiagram participant Worker as Test worker participant Main as Main process participant FS as File system Worker->>Worker: takeCoverage() - collect and filter results Worker->>Main: onAfterSuiteRun(results)<br/>structured clone (threads) / v8.serialize (forks)<br/>full results, MBs on large projects Main->>Main: JSON.stringify(results) Main->>FS: write .tmp/coverage-N.json Note over Main,FS: at report time FS->>Main: read + JSON.parse each file Main->>Main: merge, remap, reportAfter — workers write their own results in parallel; only a filename crosses the boundary:
sequenceDiagram participant Worker as Test worker participant Main as Main process participant FS as File system Worker->>Worker: takeCoverage() - collect and filter results Worker->>FS: JSON.stringify(results)<br/>write .tmp/coverage-uuid.json Worker->>Main: onAfterSuiteRun(filename)<br/>plain string, few bytes Note over Main,FS: at report time FS->>Main: read + JSON.parse each file Main->>Main: merge, remap, reportBrowser mode
Before — the v8 CDP payload made a round trip to the page and back over WebSocket (flatted), unfiltered on the way out:
sequenceDiagram participant Page as Tester page participant Main as Main process participant FS as File system rect rgba(128, 128, 128, 0.1) Note right of Page: v8 Page->>Main: __vitest_takeV8Coverage command Main->>Main: Profiler.takePreciseCoverage via CDP Main->>Page: unfiltered results over WebSocket<br/>MBs, includes node_modules and vite client Page->>Page: filter + rewrite URLs Page->>Main: onAfterSuiteRun(results) over WebSocket - MBs end rect rgba(128, 128, 128, 0.1) Note right of Page: istanbul Page->>Main: onAfterSuiteRun(coverage map) over WebSocket - full map end Main->>Main: JSON.stringify(results) Main->>FS: write .tmp/coverage-N.jsonAfter — v8 results never leave the main process; istanbul's map crosses the WebSocket once (it only exists in the page):
sequenceDiagram participant Page as Tester page participant Main as Main process participant FS as File system rect rgba(128, 128, 128, 0.1) Note right of Page: v8 Page->>Main: __vitest_takeV8Coverage(location.href) - few bytes Main->>Main: Profiler.takePreciseCoverage via CDP<br/>filter + rewrite URLs Main->>FS: write .tmp/coverage-uuid.json Main->>Page: filename end rect rgba(128, 128, 128, 0.1) Note right of Page: istanbul Page->>Main: __vitest_writeCoverageFile(coverage map)<br/>one WebSocket transfer Main->>FS: write .tmp/coverage-uuid.json Main->>Page: filename end Page->>Main: onAfterSuiteRun(filename) - few bytesPlease don't delete this checklist! Before submitting the PR, please make sure you do the following:
pnpm-lock.yamlunless you introduce a new test example.Tests
pnpm test:ci.Documentation
pnpm run docscommand.Changesets
feat:,fix:,perf:,docs:, orchore:.