refactor: outline normalize_with to reduce binary size#1222
Conversation
`PathUtil::normalize_with` and `CachedPath::normalize_with` are generic over `AsRef<Path>`, so the compiler emitted a full copy of each body for every distinct argument type across their ~30 call sites. Keep the generic signature as a thin `#[inline]` wrapper and move the body into a single non-generic instantiation, so the body is compiled once instead of per call-site type. Removes 4.94 KiB of `.text` from the napi cdylib. Perf-neutral: the inline wrapper folds away, leaving callers with a direct call to the shared impl.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1222 +/- ##
=======================================
Coverage 93.69% 93.69%
=======================================
Files 21 21
Lines 4201 4205 +4
=======================================
+ Hits 3936 3940 +4
Misses 265 265 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
## 🤖 New release * `oxc_resolver`: 11.21.2 -> 11.21.3 * `oxc_resolver_napi`: 11.21.2 -> 11.21.3 <details><summary><i><b>Changelog</b></i></summary><p> ## `oxc_resolver` <blockquote> ## [11.21.3](v11.21.2...v11.21.3) - 2026-06-18 ### <!-- 1 -->🐛 Bug Fixes - *(tsconfig)* only attach an auto-discovered tsconfig to a file it owns ([#1220](#1220)) (by @shulaoda) ### <!-- 2 -->🚜 Refactor - outline normalize_with to reduce binary size ([#1222](#1222)) (by @Boshen) ### Contributors * @Boshen * @shulaoda </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>
Merging this PR will not alter performance
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ❌ | pm/bun-flat |
936.6 µs | 996 µs | -5.97% |
| ❌ | pm/yarn-isolated |
1 ms | 1.1 ms | -5.38% |
| ❌ | pm/npm-flat |
920.9 µs | 957.3 µs | -3.81% |
| ⚡ | pm/yarn-flat |
951.1 µs | 869.8 µs | +9.35% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing refactor/outline-normalize-with (cca5205) with main (110bb35)
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. ↩
What
PathUtil::normalize_withandCachedPath::normalize_withare generic overAsRef<Path>, so the compiler emitted a full copy of each body for every distinct argument type across their ~30 call sites (&str,&Path,&PathBuf,&String, …).This keeps the public /
pub(crate)generic signature as a thin#[inline]wrapper and moves the body into a single non-generic instantiation (normalize_with_impl). The wrapper only does.as_ref()and tail-calls the shared impl, so behaviour is unchanged.Binary size
Measured on the real napi cdylib (
liboxc_resolver_napi.dylib, default features), clean stash-based A/B:.textsectionThe file size moves only −16 B because Mach-O segments are quantized to 16 KB pages — the
.textnumber is the real machine code removed, and it carries directly to the wasm build (byte-granular code section).Found with
cargo llvm-lines: both functions showed up as multi-copy monomorphizations whose per-copy bodies are identical apart from the inlinedas_ref(), so fat-LTO's function-merging could not fold them.Notes
Perf-neutral:
normalize_withis hot, but the#[inline]wrapper folds away, leaving callers with a direct call to the single shared impl — same call structure as before.