Skip to content

perf(coverage): speed up v8 report generation (bounded-memory merge + precompiled globs) - #10506

Merged
AriPerkkio merged 8 commits into
vitest-dev:mainfrom
toxik:perf/coverage-generation
Jul 14, 2026
Merged

AriPerkkio merged 8 commits into
vitest-dev:mainfrom
toxik:perf/coverage-generation

Conversation

@toxik

@toxik toxik commented Jun 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

Two independent, self-contained performance fixes to coverage report generation (generateCoverage / BaseCoverageProvider), measured on a real 1124-test-file app (~39 MB of raw V8 coverage across the run). Numbers below are best-of-3 runs, baseline vs this PR on the same machine:

Phase Before After
read + merge ~20.8s ~0.30s
convert (incl. isIncluded filtering) ~22.2s ~2.6s
total generateCoverage ~43s ~2.9s

Peak heap during coverage generation drops from ~2.5 GB → ~1.15 GB, and resident raw coverage is now bounded to ≤16 MB regardless of suite size.

isIncluded runs per covered file inside convertCoverage, so the glob fix's savings land in the convert row above; the pure astV8ToIstanbul transform (~2.6s) is itself unchanged.

Tests

No behavior change. Both fixes are verified against the existing test/coverage-test suites (v8 + istanbul), which assert coverage output and the set of included files. pnpm typecheck and pnpm lint pass. A backport to the v4 release line will follow.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the maybe automated User is likely an AI agent, or the content was generated by an AI assistant without user control label Jun 2, 2026
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown

Hello @toxik. Your PR has been labeled maybe automated because it appears to have been fully generated by AI with no human involvement.

To keep your PR open, please follow these steps:

  • Confirm that you are a real human. If you are an automated agent, disclose that
  • Confirm you've read, reviewed and stand behind its content
  • Confirm you've read the full issue along with all of its comments, as well as any linked issues and their comments
  • Make sure it follows our contribution guidelines and uses the correct GitHub template
  • Disclose any AI tools you used (e.g. Claude, Copilot, Codex)

Please, do not generate or format the response with AI. If you do not speak English, reply in your native language or use translation software like Google Translate or Deepl. If the response is generated, the PR will be closed automatically.

These measures help us reduce maintenance burden and keep the team's work efficient. See our AI contributions policy for more context.

@netlify

netlify Bot commented Jun 2, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for vitest-dev ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 6c16369
🔍 Latest deploy log https://app.netlify.com/projects/vitest-dev/deploys/6a3e8ddb15e2fb0008619d84
😎 Deploy Preview https://deploy-preview-10506--vitest-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@toxik

toxik commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Hello @toxik. Your PR has been labeled maybe automated because it appears to have been fully generated by AI with no human involvement.

To keep your PR open, please follow these steps:

  • Confirm that you are a real human. If you are an automated agent, disclose that
  • Confirm you've read, reviewed and stand behind its content
  • Confirm you've read the full issue along with all of its comments, as well as any linked issues and their comments
  • Make sure it follows our contribution guidelines and uses the correct GitHub template
  • Disclose any AI tools you used (e.g. Claude, Copilot, Codex)

Please, do not generate or format the response with AI. If you do not speak English, reply in your native language or use translation software like Google Translate or Deepl. If the response is generated, the PR will be closed automatically.

These measures help us reduce maintenance burden and keep the team's work efficient. See our AI contributions policy for more context.

Hello,

I am indeed a human and there was indeed coding agent help with this PR from Claude Code.
I've reviewed and tested the code prior to opening the PR, as well as tested it in a large project to confirm the numbers.

@sheremet-va sheremet-va removed the maybe automated User is likely an AI agent, or the content was generated by an AI assistant without user control label Jun 2, 2026
@vitest-dev vitest-dev deleted a comment from vitest-ecosystem-ci Bot Jun 3, 2026
@vitest-dev vitest-dev deleted a comment from vitest-ecosystem-ci Bot Jun 3, 2026
@vitest-ecosystem-ci

vitest-ecosystem-ci Bot commented Jun 3, 2026 •

Copy link
Copy Markdown

📝 Ran ecosystem CI: Open

suite result
vitest-coverage-large ✅ success

@AriPerkkio AriPerkkio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The early coverage map merging is there intentionally. We cannot hold all coverage results in memory at once, as it would lead to out-of-memory crashes. That's the reason why we do file-system round-trip in the first place, instead of just holding everything in memory.

Related issue:

Comment thread packages/coverage-v8/src/provider.ts Resolved
Comment thread packages/vitest/src/node/coverage.ts Resolved
toxik and others added 3 commits June 3, 2026 11:03
generateCoverage() folded mergeProcessCovs([merged, coverage]) once per coverage
file and re-scanned the growing merged.result on every file to repair
startOffset/isExtendedContext, making the read phase O(n^2) in the number of
coverage files.

Collect the raw coverages and merge them in a single pass, restoring the dropped
fields via lookup maps built while reading.

Profiled on a real 1124-test-file app: the read+merge phase dropped from ~24.5s
to ~0.3s (single merge ~95ms). Together with the isIncluded fix, total coverage
generation went from 52.8s to 7.1s.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
isIncluded() called picomatch.isMatch(file, patterns, options) per file, which
recompiles every glob into a regex on each call. The globCache does not help
during coverage filtering because each result entry has a unique filename, so
every call paid the full compile cost.

Compile the include/exclude matchers once and reuse them.

Profiled on a real 1124-test-file app: the include/exclude filtering step dropped
from ~23.3s to ~0.38s (~61x), with identical results. Together with the
single-pass merge, total coverage generation went from 52.8s to 7.1s.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@toxik
toxik force-pushed the perf/coverage-generation branch from 14a9977 to 65dd2ad Compare June 3, 2026 08:08
@toxik
toxik force-pushed the perf/coverage-generation branch from 65dd2ad to 43c3903 Compare June 3, 2026 08:10
@toxik toxik changed the title perf(coverage): speed up report generation (single-pass merge + precompiled globs) perf(coverage): speed up report generation (bounded-memory merge + precompiled globs) Jun 3, 2026
Comment thread packages/coverage-v8/src/provider.ts Resolved
@vitest-ecosystem-ci

vitest-ecosystem-ci Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

📝 Ran ecosystem CI: Open

suite result
vitest-coverage-large ✅ success

@AriPerkkio
AriPerkkio self-requested a review July 14, 2026 05:41
Comment thread packages/coverage-v8/src/provider.ts Resolved
Comment thread packages/coverage-v8/src/provider.ts Resolved
Comment thread packages/coverage-v8/src/provider.ts Resolved
Comment thread packages/vitest/src/node/coverage.ts Resolved
@vitest-ecosystem-ci

vitest-ecosystem-ci Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

📝 Ran ecosystem CI: Open

suite result
vitest-coverage-large ✅ success

@AriPerkkio AriPerkkio changed the title perf(coverage): speed up report generation (bounded-memory merge + precompiled globs) perf(coverage): speed up v8 report generation (bounded-memory merge + precompiled globs) Jul 14, 2026

@AriPerkkio AriPerkkio left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good now, thanks for addressing all the findings @toxik! 💯
Sorry for long review time.

On my machine (M4 Pro chip) I saw following improvements using artificial benchmark:

┌────────────────┬───────────────────────┬───────────────────┬─────────┐
│ coverage files │ old incremental merge │ new per-URL merge │ speedup │
├────────────────┼───────────────────────┼───────────────────┼─────────┤
│ 200            │ 77 ms                 │ 38 ms             │ 2.0x    │
├────────────────┼───────────────────────┼───────────────────┼─────────┤
│ 800            │ 795 ms                │ 125 ms            │ 6.4x    │
├────────────────┼───────────────────────┼───────────────────┼─────────┤
│ 2000           │ 5368 ms               │ 271 ms            │ 19.8x   │
└────────────────┴───────────────────────┴───────────────────┴─────────┘

Memory usage is a bit higher than in main, but it's not crashing:

@AriPerkkio
AriPerkkio merged commit b05e5d6 into vitest-dev:main Jul 14, 2026
42 of 48 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants