perf(cache): store canonical path as Box<Path> instead of PathBuf#1143
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1143 +/- ##
=======================================
Coverage 93.12% 93.12%
=======================================
Files 21 21
Lines 4089 4089
=======================================
Hits 3808 3808
Misses 281 281 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Merging this PR will improve performance by 16.41%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | complex_real |
21.6 µs | 22.4 µs | -3.5% |
| ⚡ | resolver_memory[resolve from symlinks] |
49.3 ms | 35.7 ms | +38.19% |
| ⚡ | resolver_memory[single-thread] |
425.2 µs | 384.3 µs | +10.65% |
| ⚡ | resolver_real[multi-thread] |
435 µs | 391.4 µs | +11.12% |
| ⚡ | resolver_real[resolve from symlinks] |
48.9 ms | 35.5 ms | +37.85% |
| ⚡ | resolver_real[single-thread] |
426.7 µs | 380.4 µs | +12.18% |
| ⚡ | resolver_memory[multi-thread] |
445.4 µs | 389.8 µs | +14.25% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing perf/cached-path-canonicalized-box (98617e3) with main (22fafa2)2
Footnotes
-
5 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. ↩
-
No successful run was found on
main(98617e3) during the generation of this report, so 22fafa2 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩
Merge activity
|
) ## Summary `CachedPathImpl::canonicalized` cached the canonical path as `PathBuf` even though it's set once and never mutated. `PathBuf` is `Vec<u8>`-sized (`ptr + len + cap` = 24 bytes); `Box<Path>` only needs `ptr + len` = 16 bytes. The capacity word was dead weight. Switching the field type shrinks the `OnceLock<(Weak<Self>, ...)>` tuple from 40 to 32 bytes — saving **8 bytes per cached path entry**. For a resolver session with 10k cached paths that's ~80 KB; with 100k it's ~800 KB. The setter now clones the existing `Box<Path>` of the canonical entry instead of calling `to_path_buf()`, so we don't take a PathBuf detour either. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
39f4fac to
98617e3
Compare
## 🤖 New release * `oxc_resolver`: 11.19.1 -> 11.19.2 * `oxc_resolver_napi`: 11.19.1 -> 11.19.2 <details><summary><i><b>Changelog</b></i></summary><p> ## `oxc_resolver` <blockquote> ## [11.19.2](v11.19.1...v11.19.2) - 2026-05-25 ### <!-- 1 -->🐛 Bug Fixes - *(tsconfig)* apply later-wins semantics for extends array ([#1156](#1156)) (by @Boshen) - *(tsconfig)* walk past a tsconfig that doesn't claim the file ([#1154](#1154)) (by @Boshen) - *(tsconfig)* let project references take priority over their parent ([#1151](#1151)) (by @Boshen) - *(tsconfig)* resolve `rootDirs` against the config that declared them ([#1150](#1150)) (by @Boshen) - *(tsconfig)* resolve `baseUrl` / `paths` against the canonical tsconfig path ([#1148](#1148)) (by @Boshen) - strip query fragments when calling `find_tsconfig` ([#1147](#1147)) (by @Boshen) - avoid panic in resolve_file for parentless paths ([#1053](#1053)) (by @Boshen) - *(dts)* strip ./ prefix from package entry when matching typesVersions ([#1051](#1051)) (by @Boshen) - *(dts)* expand Declaration to TypeScript|Declaration for package entry resolution ([#1050](#1050)) (by @Boshen) - *(dts)* prefer declaration extensions over JS in exports-resolved paths ([#1047](#1047)) (by @Boshen) - avoid wasm/wasi dead-code lint in NodePath ([#1043](#1043)) (by @Boshen) - *(napi)* replace panics with error returns to prevent WASM traps ([#1055](#1055)) (by @Boshen) ### <!-- 2 -->🚜 Refactor - remove clear_cache test that dynamically creates fixtures (by @Boshen) - move resolve and misc fixtures into fixtures/integration (by @Boshen) - replace ignored doctest with link to example (by @Boshen) - consolidate fixture directories for better test file mapping (by @Boshen) - replace `url` crate with `percent-encoding` ([#1065](#1065)) (by @Boshen) ### <!-- 4 -->⚡ Performance - *(cache)* pack CachedPathImpl::meta into a CachedMeta byte ([#1144](#1144)) (by @Boshen) - *(cache)* store canonical path as Box<Path> instead of PathBuf ([#1143](#1143)) (by @Boshen) - *(alias)* fast-reject alias entries by cached first byte ([#1142](#1142)) (by @Boshen) ### <!-- 6 -->🧪 Testing - *(tsconfig)* port lookup scenarios from typescript-go ([#1155](#1155)) (by @Boshen) - add 28 tests to improve coverage (92% → 93%) ([#1082](#1082)) (by @Boshen) ### Contributors * @Boshen * @renovate[bot] </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/). Co-authored-by: oxc-guard[bot] <276638029+oxc-guard[bot]@users.noreply.github.com>
Summary
CachedPathImpl::canonicalizedcached the canonical path asPathBufeven though it's set once and never mutated.PathBufisVec<u8>-sized (ptr + len + cap= 24 bytes);Box<Path>only needsptr + len= 16 bytes. The capacity word was dead weight.Switching the field type shrinks the
OnceLock<(Weak<Self>, ...)>tuple from 40 to 32 bytes — saving 8 bytes per cached path entry. For a resolver session with 10k cached paths that's ~80 KB; with 100k it's ~800 KB.The setter now clones the existing
Box<Path>of the canonical entry instead of callingto_path_buf(), so we don't take a PathBuf detour either.🤖 Generated with Claude Code