Skip to content

deps: improve macOS spawn PATH performance - #66005

Closed
splincode wants to merge 1 commit into
nodejs:mainfrom
splincode:perf/macos-spawn-path
Closed

deps: improve macOS spawn PATH performance#66005
splincode wants to merge 1 commit into
nodejs:mainfrom
splincode:perf/macos-spawn-path

Conversation

@splincode

Copy link
Copy Markdown

Refs: #62554

Summary

On macOS, resolving a child process executable through PATH currently requires libuv to manually walk every PATH entry and call posix_spawn() for each candidate.

For commands such as:

spawn('git', ...)
spawnSync('clang', ...)

this can result in multiple failed posix_spawn() calls before the executable is found, making process spawning noticeably slower with longer PATH values.

This change restores a posix_spawnp() fast path for the common case where it is safe to use.

Why this is safe

libuv previously stopped using posix_spawnp() on macOS because of a macOS bug involving posix_spawn_file_actions_addchdir_np().

The fast path added here is only used when:

  • no cwd change is requested;
  • the child PATH is identical to the parent process PATH.

This means posix_spawnp() resolves the same executable as the current manual implementation, while avoiding the macOS cwd issue.

Calls using a custom PATH or cwd continue to use the existing manual resolution path.

Benchmark

A new child_process benchmark compares PATH-based executable lookup with an absolute path while varying the number of PATH entries.

benchmark/child_process/child-process-spawn-path.js

The benchmark covers:

  • 0 additional PATH entries
  • 8 additional PATH entries
  • 32 additional PATH entries
  • PATH-based lookup
  • absolute executable path

Notes

The regression reported in #62554 is macOS-specific, so performance results should be collected on macOS before this is considered ready to land.

This change modifies the vendored libuv implementation. If this should be contributed to libuv/libuv first instead, I am happy to move the fix upstream there.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/performance
  • @nodejs/security-wg

@github-actions

Copy link
Copy Markdown
Contributor

Welcome to Node.js, and thank you for your first contribution!

Before review, please take a moment to read:

Please make sure every commit is signed off. For a first pull request, GitHub Actions require collaborator approval and Jenkins CI must be started by a collaborator or triager, so an initial wait is normal.

@nodejs-github-bot nodejs-github-bot added libuv Issues and PRs related to the libuv dependency or the uv binding. needs-ci PRs that need a full CI run. labels Sep 12, 2026
@MikeMcC399

Copy link
Copy Markdown
Contributor

Note the dependencies documentation section of the Pull requests guide:

Node.js has several bundled dependencies in the deps/ and the tools/ directories that are not part of the project proper. These are detailed in the maintaining dependencies document. Changes to files in those directories should be sent to their respective projects. Do not send a patch to Node.js. We cannot accept such patches.

Signed-off-by: splincode <omaxphp@yandex.ru>
@splincode
splincode force-pushed the perf/macos-spawn-path branch from dfc7d0e to 3d86f80 Compare September 12, 2026 18:06
@splincode

Copy link
Copy Markdown
Author

Thanks for pointing this out. I moved the change upstream to libuv:
libuv/libuv#5273

Closing this PR as the dependency update should come through libuv.

@splincode splincode closed this Sep 12, 2026
@MikeMcC399 MikeMcC399 added the wrong repo Issues that should be opened in another repository. label Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libuv Issues and PRs related to the libuv dependency or the uv binding. needs-ci PRs that need a full CI run. wrong repo Issues that should be opened in another repository.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants