Repository navigation
perf(rolldown): reduce stalls on cold session open - #633
Open
webfansplz wants to merge 2 commits into
Open
webfansplz wants to merge 2 commits into
webfansplz wants to merge 2 commits into
Conversation
@vitejs/devtools
@vitejs/devtools-kit
@vitejs/devtools-oxc
@vitejs/devtools-rolldown
@vitejs/devtools-vite
@vitejs/devtools-vitest
commit: |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Active issues cause excessive small filesystem writes that slow cold opens and incomplete metric summaries that omit hydrated counts and durations when logs grow.
2 open issues
What changed in this PR
This PR reduces event-loop stalls when opening uncached Rolldown sessions, helping keep the shared Vite dev-server process responsive during cache generation.
Changes:
- Reuses one manager snapshot and builds cache summaries in slices.
- Accumulates plugin summaries during parsing and rebuilds them on restore.
- Adds sliced JSON serialization and tests for output equivalence and summary consistency.
| File | Description |
|---|---|
packages/rolldown/src/node/rolldown/log-cache.ts |
Shares snapshots and slices cache preparation and serialization. |
packages/rolldown/src/node/rolldown/events-manager.ts |
Tracks incremental plugin summaries through parsing, restore, and disposal. |
packages/rolldown/src/node/rolldown/__tests__/cold-open-cache.test.ts |
Tests plugin summary consistency and serialized JSON equivalence. |
Review effort: Balanced
Comment on lines
+188
to
+189
| summary = createEmptyPluginBuildMetricsSummary(pluginId, pluginName) | ||
| this.plugin_build_summaries.set(pluginId, summary) |
| const temporaryFilepath = `${this.filepath}.tmp` | ||
| await fs.mkdir(dirname(this.filepath), { recursive: true }) | ||
| await fs.writeFile(temporaryFilepath, JSON.stringify(this.createFile(stat, data)), 'utf8') | ||
| await fs.writeFile(temporaryFilepath, await stringifyInSlices(this.createFile(stat, data)), 'utf8') |
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
When a Rolldown session is opened for the first time, the DevTools server parses
logs.jsonand then writes the.cache/sidecars. Writing those sidecars blocked the event loop in large chunks: building the module metrics and plugin summaries ran in one synchronous pass, and each sidecar was serialized with a singleJSON.stringify(41 MB of module metrics on a large project). When DevTools runs inside the Vite dev server, this shares the process with Vite, so page loads and HMR stalled too.This PR keeps the cache output identical and splits that work so the server stays responsive.
Changes
manager.snapshot()is shared across the sidecars (it was taken three to four times), and module metrics compaction and plugin summaries are built entry by entry, yielding about every 8 ms.RolldownEventsManagerkeepsplugin_build_summariesin step withplugin_build_metrics, so writing the plugin summary no longer rescans every call. Summaries are rebuilt onrestoreand cleared ondispose; metrics hydrated from the index fall back to computing from calls.stringifyInSlicesproduces the same output asJSON.stringify, but serializes large arrays item by item and yields in between.Impact
Measured locally on a lobehub SPA build log (~29k modules, 6.9M events, 4 GB), cold open with no cache, 5 runs each:
The total cold-open time is unchanged; it's dominated by parsing the log.