Skip to content

perf: optimize absolutize to avoid allocation for already-absolute paths#34

Merged
hyf0 merged 2 commits intomainfrom
hyf_32849023842
Feb 23, 2026
Merged

perf: optimize absolutize to avoid allocation for already-absolute paths#34
hyf0 merged 2 commits intomainfrom
hyf_32849023842

Conversation

@hyf0
Copy link
Copy Markdown
Owner

@hyf0 hyf0 commented Feb 23, 2026

No description provided.

Copilot AI review requested due to automatic review settings February 23, 2026 13:43
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Feb 23, 2026

Merging this PR will improve performance by 48.14%

⚡ 4 improved benchmarks
✅ 25 untouched benchmarks
⏩ 1 skipped benchmark1

Performance Changes

Benchmark BASE HEAD Efficiency
absolutize_with 10.4 µs 7 µs +47.53%
absolutize_already_clean_absolute 24 µs 21.3 µs +13.04%
absolutize 24.3 µs 21.3 µs +14.11%
absolutize_with_already_clean_absolute 10.4 µs 7 µs +48.14%

Comparing hyf_32849023842 (26e5a91) with main (5585dd3)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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() and absolutize_with() from PathBuf to Cow<'_, Path> in trait definition and implementations
  • Updated internal call sites to use .into_owned() where PathBuf is 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
@hyf0 hyf0 merged commit 206fd50 into main Feb 23, 2026
5 checks passed
@github-actions github-actions bot mentioned this pull request Feb 23, 2026
graphite-app bot pushed a commit to rolldown/rolldown that referenced this pull request Feb 23, 2026
## 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)
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