Skip to content

perf(vite-resolve): cache importer existence checks#9443

Merged
graphite-app[bot] merged 1 commit into
mainfrom
codex/cache-vite-importer-exists
May 19, 2026
Merged

perf(vite-resolve): cache importer existence checks#9443
graphite-app[bot] merged 1 commit into
mainfrom
codex/cache-vite-importer-exists

Conversation

@Brooooooklyn

@Brooooooklyn Brooooooklyn commented May 18, 2026

Copy link
Copy Markdown
Member

Summary

  • share Vite resolver caches through a small internal ResolverCaches object
  • cache positive fs::exists(clean_url(importer)) results for absolute importers in should_use_importer
  • avoid caching negative existence results so watch rebuilds can observe files that appear later
  • clear the importer-existence cache together with the existing resolver caches

Performance note

This came from the LobeHub renderer profiling work. System Trace showed this path reducing repeated stat64 calls in the resolver-heavy capture (66102 -> 52656, about 20%). The isolated LobeHub wall-clock benchmark did not show a measurable win: local without this cache was 8.508s ± 0.049, and local with this cache was 8.523s ± 0.041. So this should be reviewed as a syscall/cache reduction, not as a confirmed build-time speedup.

Validation

  • cargo fmt --check
  • cargo check -p rolldown_plugin_vite_resolve
  • cargo clippy -p rolldown_plugin_vite_resolve --all-targets -- -D warnings
  • cargo test -p rolldown_plugin_vite_resolve
  • pnpm --filter rolldown run build-native:release
  • pnpm --filter vite-tests test

Note

Low Risk
Low risk performance tweak in resolver logic; behavior should be unchanged aside from caching positive fs::exists results, with cache cleared on clear_cache() to avoid stale state across rebuilds.

Overview
Reduces repeated filesystem exists/stat calls in the Vite resolver by introducing a shared ResolverCaches object that is reused across all Resolver instances.

should_use_importer now memoizes positive fs::exists(clean_url(importer)) checks for absolute importers (and still skips caching negatives), and Resolvers::clear_cache() clears this new importer-existence cache alongside existing resolver caches.

Reviewed by Cursor Bugbot for commit 0e5fc81. Bugbot is set up for automated code reviews on this repo. Configure here.

@netlify

netlify Bot commented May 18, 2026

Copy link
Copy Markdown

Deploy Preview for rolldown-rs canceled.

Name Link
🔨 Latest commit 886329c
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/6a0bfb5af69ccb0008f0efb7

@Brooooooklyn Brooooooklyn force-pushed the codex/cache-vite-importer-exists branch from f251230 to 940e617 Compare May 18, 2026 13:34
@Brooooooklyn Brooooooklyn marked this pull request as ready for review May 18, 2026 13:57
@Brooooooklyn Brooooooklyn requested a review from sapphi-red May 18, 2026 13:58

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 940e617. Configure here.

Comment thread crates/rolldown_plugin_vite_resolve/src/resolver.rs Outdated
@codspeed-hq

codspeed-hq Bot commented May 18, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 4 untouched benchmarks
⏩ 10 skipped benchmarks1


Comparing codex/cache-vite-importer-exists (0e5fc81) with main (a91bd20)

Open in CodSpeed

Footnotes

  1. 10 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Brooooooklyn Brooooooklyn force-pushed the codex/cache-vite-importer-exists branch from 940e617 to 0e5fc81 Compare May 18, 2026 14:14
@hyf0 hyf0 assigned sapphi-red and unassigned Brooooooklyn May 18, 2026

sapphi-red commented May 19, 2026

Copy link
Copy Markdown
Member

Merge activity

  • May 19, 5:55 AM UTC: The merge label 'graphite: merge-when-ready' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • May 19, 5:55 AM UTC: sapphi-red added this pull request to the Graphite merge queue.
  • May 19, 6:00 AM UTC: Merged by the Graphite merge queue.

### Summary

- share Vite resolver caches through a small internal `ResolverCaches` object
- cache positive `fs::exists(clean_url(importer))` results for absolute importers in `should_use_importer`
- avoid caching negative existence results so watch rebuilds can observe files that appear later
- clear the importer-existence cache together with the existing resolver caches

### Performance note

This came from the LobeHub renderer profiling work. System Trace showed this path reducing repeated `stat64` calls in the resolver-heavy capture (`66102 -> 52656`, about 20%). The isolated LobeHub wall-clock benchmark did not show a measurable win: local without this cache was `8.508s ± 0.049`, and local with this cache was `8.523s ± 0.041`. So this should be reviewed as a syscall/cache reduction, not as a confirmed build-time speedup.

### Validation

- `cargo fmt --check`
- `cargo check -p rolldown_plugin_vite_resolve`
- `cargo clippy -p rolldown_plugin_vite_resolve --all-targets -- -D warnings`
- `cargo test -p rolldown_plugin_vite_resolve`
- `pnpm --filter rolldown run build-native:release`
- `pnpm --filter vite-tests test`

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk performance tweak in resolver logic; behavior should be unchanged aside from caching positive `fs::exists` results, with cache cleared on `clear_cache()` to avoid stale state across rebuilds.
>
> **Overview**
> Reduces repeated filesystem `exists`/`stat` calls in the Vite resolver by introducing a shared `ResolverCaches` object that is reused across all `Resolver` instances.
>
> `should_use_importer` now memoizes *positive* `fs::exists(clean_url(importer))` checks for absolute importers (and still skips caching negatives), and `Resolvers::clear_cache()` clears this new importer-existence cache alongside existing resolver caches.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0e5fc81. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@graphite-app graphite-app Bot force-pushed the codex/cache-vite-importer-exists branch from 0e5fc81 to 886329c Compare May 19, 2026 05:55
@graphite-app graphite-app Bot merged commit 886329c into main May 19, 2026
32 checks passed
@graphite-app graphite-app Bot deleted the codex/cache-vite-importer-exists branch May 19, 2026 06:00
@rolldown-guard rolldown-guard Bot mentioned this pull request May 20, 2026
shulaoda added a commit that referenced this pull request May 20, 2026
## [1.0.2] - 2026-05-20

### 🚀 Features

- devtools: emit package size in PackageGraphReady (#9434) by @IWANABETHATGUY
- devtools: classify package dependency types (#9427) by @IWANABETHATGUY
- devtools: map packages to modules and chunks (#9426) by @IWANABETHATGUY
- devtools: mark used packages (#9423) by @IWANABETHATGUY
- devtools: make duplicate packages discoverable (#9422) by @IWANABETHATGUY
- devtools: emit package metadata (#9421) by @IWANABETHATGUY
- update oxc to 0.132.0 (#9449) by @shulaoda
- update oxc to 0.131.0 (#9424) by @shulaoda
- allow checks.* to escalate emissions to hard errors (#9388) by @IWANABETHATGUY
- dev: support watcher options `include` and `exclude` (#9395) by @h-a-n-a
- emit warnings for invalid pure annotations (#9381) by @Kyujenius

### 🐛 Bug Fixes

- hash: keep chunk file names stable when an unrelated entry is added (#9444) by @hyf0
- call `codeSplitting.groups[].name` in deterministic order (#9457) by @sapphi-red
- dev/lazy: make `resolve_id` idempotent when the resolved id is already a lazy entry (#9439) by @h-a-n-a
- chunk-optimization: publish absorbed dynamic-entry namespace cross-chunk (#9448) by @IWANABETHATGUY
- treeshake: propagate pure annotation through compound exprs (#9431) by @Dunqing
- finalizer: skip redundant init call when barrel executes in same chunk (#9354) by @IWANABETHATGUY
- linking: initialize wrapped ESM re-export owners (#9353) by @IWANABETHATGUY
- do not inherit __toESM across chunks for named-only external imports (#9333) (#9415) by @IWANABETHATGUY
- watcher: don't write output or emit events after close() (#9328) by @situ2001
- chunk-optimization: avoid unsafe dynamic-only merges (#9398) by @IWANABETHATGUY
- cjs: rename CJS-wrapped locals that would shadow chunk-scope names (#9392) by @hyf0
- dev/lazy: watch lazy modules added in rebuilds (#9391) by @h-a-n-a

### 🚜 Refactor

- rolldown_dev: move dev example to break publish cycle (#9465) by @Boshen
- binding: drop unsafe napi string helper, hoist transform ArcStr (#9456) by @hyf0
- ecmascript_utils: split rewrite_ident_reference off JsxExt trait (#9417) by @IWANABETHATGUY
- use `ThreadsafeFunction::call_async_catch` (#9390) by @sapphi-red

### 📚 Documentation

- devtools: document @rolldown/debug usage and package graph consumption (#9435) by @IWANABETHATGUY
- replace `Inter` with system font stack in OG template SVG (#9240) by @yvbopeng
- remove `output.comments` warning as all issues have been resolved (#9393) by @sapphi-red
- in-depth: clarify @__PURE__ scope and document positions (#9389) by @Kyujenius
- readme: remove release candidate notice (#9387) by @shulaoda

### ⚡ Performance

- vite-resolve: cache importer existence checks (#9443) by @Brooooooklyn
- binding: reduce plugin string clones (#9436) by @Brooooooklyn

### 🧪 Testing

- enable `legal_comments_inline` test (#9394) by @sapphi-red

### ⚙️ Miscellaneous Tasks

- bump pnpm to v11.1.2 (#9447) by @Boshen
- deps: update rust crates (#9461) by @renovate[bot]
- deps: update rollup submodule for tests to v4.60.4 (#9453) by @rolldown-guard[bot]
- deps: update test262 submodule for tests (#9454) by @rolldown-guard[bot]
- deps: update npm packages (#9430) by @renovate[bot]
- deps: update github actions (#9429) by @renovate[bot]
- deps: update dependency rolldown-plugin-dts to v0.25.1 (#9452) by @renovate[bot]
- deps: update rust crates (#9428) by @renovate[bot]
- revert allow checks.* to escalate emissions to hard errors (#9388) (#9438) by @IWANABETHATGUY
- update mimalloc-safe to 0.1.61 (#9413) by @shulaoda
- deny `todo`, `unimplemented`, and `print_stderr` clippy lints (#9412) by @Boshen
- deps: update mimalloc-safe to 0.1.60 (#9410) by @shulaoda
- remove `pip install setuptools` workaround for node-gyp on macOS (#9370) by @sapphi-red
- renovate: disable automerge to require manual approval (#9386) by @shulaoda
- deps: update napi (#9385) by @renovate[bot]

### ❤️ New Contributors

* @yvbopeng made their first contribution in [#9240](#9240)

Co-authored-by: shulaoda <[email protected]>
V1OL3TF0X pushed a commit to V1OL3TF0X/rolldown that referenced this pull request May 25, 2026
### Summary

- share Vite resolver caches through a small internal `ResolverCaches` object
- cache positive `fs::exists(clean_url(importer))` results for absolute importers in `should_use_importer`
- avoid caching negative existence results so watch rebuilds can observe files that appear later
- clear the importer-existence cache together with the existing resolver caches

### Performance note

This came from the LobeHub renderer profiling work. System Trace showed this path reducing repeated `stat64` calls in the resolver-heavy capture (`66102 -> 52656`, about 20%). The isolated LobeHub wall-clock benchmark did not show a measurable win: local without this cache was `8.508s ± 0.049`, and local with this cache was `8.523s ± 0.041`. So this should be reviewed as a syscall/cache reduction, not as a confirmed build-time speedup.

### Validation

- `cargo fmt --check`
- `cargo check -p rolldown_plugin_vite_resolve`
- `cargo clippy -p rolldown_plugin_vite_resolve --all-targets -- -D warnings`
- `cargo test -p rolldown_plugin_vite_resolve`
- `pnpm --filter rolldown run build-native:release`
- `pnpm --filter vite-tests test`

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk performance tweak in resolver logic; behavior should be unchanged aside from caching positive `fs::exists` results, with cache cleared on `clear_cache()` to avoid stale state across rebuilds.
>
> **Overview**
> Reduces repeated filesystem `exists`/`stat` calls in the Vite resolver by introducing a shared `ResolverCaches` object that is reused across all `Resolver` instances.
>
> `should_use_importer` now memoizes *positive* `fs::exists(clean_url(importer))` checks for absolute importers (and still skips caching negatives), and `Resolvers::clear_cache()` clears this new importer-existence cache alongside existing resolver caches.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 0e5fc81. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
V1OL3TF0X pushed a commit to V1OL3TF0X/rolldown that referenced this pull request May 25, 2026
## [1.0.2] - 2026-05-20

### 🚀 Features

- devtools: emit package size in PackageGraphReady (rolldown#9434) by @IWANABETHATGUY
- devtools: classify package dependency types (rolldown#9427) by @IWANABETHATGUY
- devtools: map packages to modules and chunks (rolldown#9426) by @IWANABETHATGUY
- devtools: mark used packages (rolldown#9423) by @IWANABETHATGUY
- devtools: make duplicate packages discoverable (rolldown#9422) by @IWANABETHATGUY
- devtools: emit package metadata (rolldown#9421) by @IWANABETHATGUY
- update oxc to 0.132.0 (rolldown#9449) by @shulaoda
- update oxc to 0.131.0 (rolldown#9424) by @shulaoda
- allow checks.* to escalate emissions to hard errors (rolldown#9388) by @IWANABETHATGUY
- dev: support watcher options `include` and `exclude` (rolldown#9395) by @h-a-n-a
- emit warnings for invalid pure annotations (rolldown#9381) by @Kyujenius

### 🐛 Bug Fixes

- hash: keep chunk file names stable when an unrelated entry is added (rolldown#9444) by @hyf0
- call `codeSplitting.groups[].name` in deterministic order (rolldown#9457) by @sapphi-red
- dev/lazy: make `resolve_id` idempotent when the resolved id is already a lazy entry (rolldown#9439) by @h-a-n-a
- chunk-optimization: publish absorbed dynamic-entry namespace cross-chunk (rolldown#9448) by @IWANABETHATGUY
- treeshake: propagate pure annotation through compound exprs (rolldown#9431) by @Dunqing
- finalizer: skip redundant init call when barrel executes in same chunk (rolldown#9354) by @IWANABETHATGUY
- linking: initialize wrapped ESM re-export owners (rolldown#9353) by @IWANABETHATGUY
- do not inherit __toESM across chunks for named-only external imports (rolldown#9333) (rolldown#9415) by @IWANABETHATGUY
- watcher: don't write output or emit events after close() (rolldown#9328) by @situ2001
- chunk-optimization: avoid unsafe dynamic-only merges (rolldown#9398) by @IWANABETHATGUY
- cjs: rename CJS-wrapped locals that would shadow chunk-scope names (rolldown#9392) by @hyf0
- dev/lazy: watch lazy modules added in rebuilds (rolldown#9391) by @h-a-n-a

### 🚜 Refactor

- rolldown_dev: move dev example to break publish cycle (rolldown#9465) by @Boshen
- binding: drop unsafe napi string helper, hoist transform ArcStr (rolldown#9456) by @hyf0
- ecmascript_utils: split rewrite_ident_reference off JsxExt trait (rolldown#9417) by @IWANABETHATGUY
- use `ThreadsafeFunction::call_async_catch` (rolldown#9390) by @sapphi-red

### 📚 Documentation

- devtools: document @rolldown/debug usage and package graph consumption (rolldown#9435) by @IWANABETHATGUY
- replace `Inter` with system font stack in OG template SVG (rolldown#9240) by @yvbopeng
- remove `output.comments` warning as all issues have been resolved (rolldown#9393) by @sapphi-red
- in-depth: clarify @__PURE__ scope and document positions (rolldown#9389) by @Kyujenius
- readme: remove release candidate notice (rolldown#9387) by @shulaoda

### ⚡ Performance

- vite-resolve: cache importer existence checks (rolldown#9443) by @Brooooooklyn
- binding: reduce plugin string clones (rolldown#9436) by @Brooooooklyn

### 🧪 Testing

- enable `legal_comments_inline` test (rolldown#9394) by @sapphi-red

### ⚙️ Miscellaneous Tasks

- bump pnpm to v11.1.2 (rolldown#9447) by @Boshen
- deps: update rust crates (rolldown#9461) by @renovate[bot]
- deps: update rollup submodule for tests to v4.60.4 (rolldown#9453) by @rolldown-guard[bot]
- deps: update test262 submodule for tests (rolldown#9454) by @rolldown-guard[bot]
- deps: update npm packages (rolldown#9430) by @renovate[bot]
- deps: update github actions (rolldown#9429) by @renovate[bot]
- deps: update dependency rolldown-plugin-dts to v0.25.1 (rolldown#9452) by @renovate[bot]
- deps: update rust crates (rolldown#9428) by @renovate[bot]
- revert allow checks.* to escalate emissions to hard errors (rolldown#9388) (rolldown#9438) by @IWANABETHATGUY
- update mimalloc-safe to 0.1.61 (rolldown#9413) by @shulaoda
- deny `todo`, `unimplemented`, and `print_stderr` clippy lints (rolldown#9412) by @Boshen
- deps: update mimalloc-safe to 0.1.60 (rolldown#9410) by @shulaoda
- remove `pip install setuptools` workaround for node-gyp on macOS (rolldown#9370) by @sapphi-red
- renovate: disable automerge to require manual approval (rolldown#9386) by @shulaoda
- deps: update napi (rolldown#9385) by @renovate[bot]

### ❤️ New Contributors

* @yvbopeng made their first contribution in [rolldown#9240](rolldown#9240)

Co-authored-by: shulaoda <[email protected]>
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.

2 participants