Skip to content

path: remove StringPrototypeCharCodeAt from more posix methods - #63662

Open
whoekage wants to merge 1 commit into
nodejs:mainfrom
whoekage:perf/path-posix-indexing-extend
Open

path: remove StringPrototypeCharCodeAt from more posix methods#63662
whoekage wants to merge 1 commit into
nodejs:mainfrom
whoekage:perf/path-posix-indexing-extend

Conversation

@whoekage

Copy link
Copy Markdown

Summary

Extends the optimization landed in #54546 (posix.extname) to the remaining POSIX path methods still using StringPrototypeCharCodeAt. #54668 covers resolve/normalize/parse; this PR covers dirname, basename, and relative.

What changed

Replaced StringPrototypeCharCodeAt(path, i) === CHAR_FORWARD_SLASH with path[i] === '/' in three POSIX methods. Diff: +12 / −14 lines in lib/path.js.

Benchmark

Apple M1, 30 runs via benchmark/compare.js. Showing significant cases:

dirname-posix

path delta sig
/foo +12.45% ***
/foo/bar/baz/asdf/quux +8.82% ***
/foo/bar +8.82% ***
foo +6.34% *
foo/bar +2.26% *

basename-posix

pathext delta sig
/foo/bar/baz/asdf/quux.html|.html +8.38% ***
/foo/.bar.baz|.baz +8.25% ***
/foo/.bar.baz +6.90% ***
foo/bar. +5.94% ***
foo +5.78% *

relative-posix

paths delta sig
/var|/bin +3.28% **

Methodology validation

Control benchmark on extname-posix (unchanged in this PR) shows ±2% deltas without statistical significance, confirming methodology. No regressions on Win32 paths (slow path untouched).

Test plan

  • parallel/test-path* — all 17 pass
  • parallel/test-url-* — all 15 pass
  • parallel/test-fs-readfile/stat/realpath — pass
  • parallel/test-module-* — all 32 pass
  • Fuzz: 425 input cases identical to baseline
  • make lint-js — clean

Refs: #54546, #54668

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/path

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. path Issues and PRs related to the path subsystem. labels May 30, 2026
@whoekage

whoekage commented Jun 5, 2026

Copy link
Copy Markdown
Author

Hi! Could a collaborator start CI here when convenient? The change is small
(+12/-14) and the path tests pass locally.

This extends the same StringPrototypeCharCodeAt(...) === CHAR_* to
path[i] === '*' conversion that was already accepted in #54546 (merged,
posix.extname) and is in progress in #54668, applied to the remaining posix
methods.

Related C++ path optimization: #63753.

Thanks!

@avivkeller avivkeller added author ready PRs that have at least one approval, no outstanding review comments, and a CI started. request-ci Add this label to start a Jenkins CI on a PR. labels Jul 25, 2026
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jul 25, 2026
@nodejs-github-bot

This comment was marked as outdated.

@nodejs-github-bot

This comment was marked as outdated.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@trivikr trivikr added commit-queue Add this label to land a pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Aug 20, 2026
@trivikr

trivikr commented Aug 20, 2026

Copy link
Copy Markdown
Member

@whoekage Can you sign your commit and force push?

It's required as per updated instructions

Your commit must contain the Signed-off-by line with your name and email address as an acknowledgement that you agree to the Developer Certificate of Origin

@trivikr trivikr removed the author ready PRs that have at least one approval, no outstanding review comments, and a CI started. label Aug 20, 2026
Extends the optimization applied to posix.extname in nodejs#54546 to
posix.dirname, posix.basename, and posix.relative. nodejs#54668 covers
posix.resolve, posix.normalize, and posix.parse.

Replacing `StringPrototypeCharCodeAt(path, i) === CHAR_FORWARD_SLASH`
with `path[i] === '/'` is consistently faster on V8 because the
single-character string comparison hits a faster path than the
integer comparison after charCodeAt().

Benchmark (Apple M1, 30 runs via benchmark/compare.js):

  dirname-posix:
    path='/foo'                                  +12.45% ***
    path='/foo/bar/baz/asdf/quux'                 +8.82% ***
    path='/foo/bar'                               +8.82% ***
    path='foo'                                    +6.34% *
    path='foo/bar'                                +2.26% *

  basename-posix:
    pathext='/foo/bar/baz/asdf/quux.html|.html'   +8.38% ***
    pathext='/foo/.bar.baz|.baz'                  +8.25% ***
    pathext='/foo/.bar.baz'                       +6.90% ***
    pathext='foo/bar.'                            +5.94% ***
    pathext='foo'                                 +5.78% *

  relative-posix:
    paths='/var|/bin'                             +3.28% **

No regressions in Win32 paths (slow path untouched). Control
benchmark on extname (unchanged) shows ±2% noise without
significance, confirming methodology.

Signed-off-by: sharkaev.ph <sharkaev.ph@gmail.com>
@whoekage
whoekage force-pushed the perf/path-posix-indexing-extend branch from 5523055 to 3b3bb25 Compare August 26, 2026 08:04
@whoekage

Copy link
Copy Markdown
Author

@trivikr Done.
Signed off and force-pushed. The diff is unchanged, only the commit message now carries the Signed-off-by line. Could you kick off a fresh CI run when you get a chance?

@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.06%. Comparing base (79def6d) to head (3b3bb25).
⚠️ Report is 1081 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #63662      +/-   ##
==========================================
- Coverage   90.32%   90.06%   -0.26%     
==========================================
  Files         732      751      +19     
  Lines      236435   254418   +17983     
  Branches    44527    47964    +3437     
==========================================
+ Hits       213563   229151   +15588     
- Misses      14589    16446    +1857     
- Partials     8283     8821     +538     
Files with missing lines Coverage Δ
lib/path.js 97.48% <100.00%> (-0.01%) ⬇️

... and 442 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@trivikr trivikr added the needs-benchmark-ci PR that need a benchmark CI run. label Aug 26, 2026
@trivikr

trivikr commented Aug 26, 2026

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-benchmark-ci PR that need a benchmark CI run. needs-ci PRs that need a full CI run. path Issues and PRs related to the path subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants