perf(cache): pack CachedPathImpl::meta into a CachedMeta byte#1144
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 21311dc7dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1144 +/- ##
==========================================
- Coverage 93.12% 93.11% -0.02%
==========================================
Files 21 22 +1
Lines 4089 4139 +50
==========================================
+ Hits 3808 3854 +46
- Misses 281 285 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Merging this PR will degrade performance by 3.69%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
21311dc to
5e7e087
Compare
5e7e087 to
c831047
Compare
Merge activity
|
## Summary
`CachedPathImpl::meta` was a `OnceLock<Option<(bool, bool)>>` (16 bytes) recording whether the path is a file and/or directory. Filesystem metadata is idempotent — `OnceLock`'s exactly-once initialization is a nicety, not a correctness requirement: if two threads race they both re-`stat` and both store the same answer.
This PR introduces a `CachedMeta` struct in `src/cache/cached_meta.rs` that wraps an `AtomicU8`, encapsulates the encoding of the six possible states (uninitialized / `None` / the four `(is_file, is_dir)` combinations), and exposes a single `get_or_init` accessor.
`CachedPathImpl::meta` becomes:
```rust
pub meta: CachedMeta,
```
…and the accessor on `CachedPath` collapses to a one-liner:
```rust
fn metadata<Fs: FileSystem>(&self, fs: &Fs) -> Option<(bool, bool)> {
self.meta.get_or_init(|| fs.metadata(&self.path).ok().map(|r| (r.is_file, r.is_dir)))
}
```
All encoding/decoding/`AtomicU8` plumbing is private to the new module.
## Size impact
The field shrinks from 16 bytes to 1, saving **15 bytes per cached path entry**. For sessions with 10k cached paths that's ~150 KB; with 100k it's ~1.5 MB.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
c831047 to
72a163c
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::metawas aOnceLock<Option<(bool, bool)>>(16 bytes) recording whether the path is a file and/or directory. Filesystem metadata is idempotent —OnceLock's exactly-once initialization is a nicety, not a correctness requirement: if two threads race they both re-statand both store the same answer.This PR introduces a
CachedMetastruct insrc/cache/cached_meta.rsthat wraps anAtomicU8, encapsulates the encoding of the six possible states (uninitialized /None/ the four(is_file, is_dir)combinations), and exposes a singleget_or_initaccessor.CachedPathImpl::metabecomes:…and the accessor on
CachedPathcollapses to a one-liner:All encoding/decoding/
AtomicU8plumbing is private to the new module.Size impact
The field shrinks from 16 bytes to 1, saving 15 bytes per cached path entry. For sessions with 10k cached paths that's ~150 KB; with 100k it's ~1.5 MB.
🤖 Generated with Claude Code