perf: optimize absolutize to avoid allocation for already-absolute paths#34
perf: optimize absolutize to avoid allocation for already-absolute paths#34
absolutize to avoid allocation for already-absolute paths#34Conversation
Merging this PR will improve performance by 48.14%
Performance Changes
Comparing Footnotes
|
There was a problem hiding this comment.
Pull request overview
This PR optimizes the absolutize and absolutize_with methods to avoid unnecessary allocations when the input path is already absolute and clean. The optimization changes the return type from PathBuf to Cow<'_, Path>, enabling zero-allocation returns via Cow::Borrowed for paths that don't need modification.
Changes:
- Changed return type of
absolutize()andabsolutize_with()fromPathBuftoCow<'_, Path>in trait definition and implementations - Updated internal call sites to use
.into_owned()wherePathBufis still needed - Added comprehensive tests to verify the optimization works correctly for both Unix and Windows paths
- Added AGENTS.md documentation file with repository conventions and CLAUDE.md reference file
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/sugar_path.rs | Updated trait method signatures to return Cow<'_, Path> instead of PathBuf |
| src/impl_sugar_path.rs | Implemented the optimization in absolutize() and absolutize_with(), updated internal call sites to use .into_owned() where needed |
| tests/absolutize_with.rs | Added comprehensive tests verifying zero-allocation behavior for clean absolute paths and allocation behavior for relative/dirty paths on both Unix and Windows |
| CLAUDE.md | Added reference file (contains only "AGENTS.md" text) |
| AGENTS.md | Added repository documentation with commands, architecture, and conventions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix Windows test: `\foo\bar` and `\` are root-relative (not absolute) on Windows — move to allocated test group - Add NOTE comment on why `absolutize_with` return lifetime is not unified with base's lifetime - Fix AGENTS.md header to match filename
## Summary Bump `sugar_path` from 1.2.1 to 2^ ### What changed in sugar_path 2.0 The 2.0 release is focused on reducing allocations in hot paths. The key optimizations: - **`normalize()` returns `Cow<'_, Path>` instead of `PathBuf`** — a `needs_normalization()` fast-path check (using `memchr`) detects already-clean paths and returns `Cow::Borrowed` with zero allocation ([#32](hyf0/sugar_path#32)) - **`absolutize()` / `absolutize_with()` return `Cow<'_, Path>`** — same idea: already-absolute clean paths are returned borrowed ([#34](hyf0/sugar_path#34)) - **`memchr`-accelerated fast path for `relative()`** — replaces the component-iterator approach with SIMD-accelerated `/` scanning, avoids the `absolutize()` → `current_dir()` syscall when both paths are already absolute, and uses `SmallVec<[&str; 8]>` to stay on the stack ([#27](hyf0/sugar_path#27)) - **Reduced allocations across the board** — reuse buffers, `SmallVec` for component lists, avoid `collect()` into `Vec` ([#26](hyf0/sugar_path#26)) ### Breaking change `normalize()`, `absolutize()`, and `absolutize_with()` now return `Cow<'_, Path>` instead of `PathBuf`. Call sites that need an owned `PathBuf` require `.into_owned()`, and chained operations like `.join().normalize().to_slash_lossy()` need to be split so the intermediate `Cow` lives long enough. ## Test plan - [x] CI passes (same API surface, just `Cow` unwrapping at call sites)
No description provided.