Repository navigation
[Perf] nvm use: skip re-resolving an exact, installed version - #3937
Merged
ljharb merged 2 commits intoOct 8, 2026
Merged
Conversation
When `nvm use` is given an exact `vX.Y.Z` that is already installed, and no alias with that exact name exists, use it directly instead of re-resolving it through `nvm_match_version` and `nvm_ensure_version_installed`, both of which call `nvm_version`. `nvm_auto` takes this path on every shell startup with an already-resolved version, so this removes ~95ms from each new shell (~330ms -> ~235ms in a clean environment on macOS/zsh). Fixes nvm-sh#3930
hridhinvarkeyjoseph
force-pushed
the
perf/use-exact-version-fast-path
branch
2 times, most recently
from
October 1, 2026 09:52
5a60628 to
c96b0d7
Compare
Contributor
Author
|
Pushed a fix for the bash-only failure: the new helper needed to be added to The one remaining failure ( |
This was referenced Oct 2, 2026
…stalled version See nvm-sh#3416
Contributor
Author
|
Folded in the change from #3945 (skip nvm_version in nvm_resolve_local_alias for an exact, installed version), since both are the same fast path on the startup route — one PR to review instead of two. |
ljharb
force-pushed
the
perf/use-exact-version-fast-path
branch
from
October 7, 2026 23:27
9fca02a to
6df817b
Compare
ljharb
approved these changes
Oct 7, 2026
ljharb
left a comment
Member
There was a problem hiding this comment.
i tweaked the second commit to use the helper the first commit introduced.
ljharb
force-pushed
the
perf/use-exact-version-fast-path
branch
from
October 8, 2026 18:14
6df817b to
913b8cb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3930.
Problem
On every new shell,
nvm.shcallsnvm_auto use. With no node onPATHyet,nvm_autoresolves thedefaultalias to an exact installed version (e.g.v24.21.0) and then calls:nvm usethen resolves that already-exact version from scratch, twice:VERSION="$(nvm_match_version "${PROVIDED_VERSION}")"→nvm_versionnvm_ensure_version_installed "${VERSION}" ...→nvm_versionagain, thennvm_is_version_installedEach
nvm_versioncall does alias resolution plusnvm_ls, forking several subshells. The existing code already flagged this spot:Profiling (master, clean
env -ienvironment, avg of 10 calls)nvm use --silent v24.21.0nvm_ensure_version_installed v24.21.0nvm_version v24.21.0About 105ms of the 168ms is spent re-deriving a version that is already exact. Changing my
defaultalias from24tov24.21.0made no difference (~290ms either way), so exact versions go through the full resolution path too.Change
Adds
nvm_is_installed_exact_version, a cheap check that returns success only when the argument:vX.Y.Z(digits and dots only, sov12,v12.0,v12.0.0-rc.1,node,lts/*,iojs-v1.0.0,system, etc. do not qualify),nvm_version, so this preserves that), andnvm_is_version_installed(executablebin/node, ornode.exeon Windows; respects the old directory layout vianvm_version_path).When it passes,
nvm usesetsVERSIONdirectly and skipsnvm_match_versionandnvm_ensure_version_installed. Everything after that is unchanged: PATH/MANPATH,NVM_BIN/NVM_INC,hash -r, thecurrentsymlink,nvm_die_on_prefix,--save, and output.All other inputs (partial versions, aliases,
lts/*,--lts,system,iojs,.nvmrc, and versions that aren't installed) go through the existing code path, so their behavior and error messages are identical.Results
Sourcing
nvm.shin a clean environment (env -i), macOS arm64, zsh, one installed Node version,defaultalias =24(avg of 4 warm runs):That's roughly 95ms (~29%) saved on every new shell. Users with more installed versions or slower
forkshould see a larger absolute saving, since the skipped code callsnvm_ls.Tests
test/fast/Unit tests/nvm_is_installed_exact_versioncovers: no argument; exact version not installed; non-executablenodebinary; installed exact version; a range of non-exact inputs (12.0.0,12,v12,v12.0,v12.0.0-rc.1,node,stable,lts/*,iojs-v1.0.0,system,default); and an alias namedv12.0.0taking precedence over the fast path.nvm_is_version_installed,nvm_ensure_version_installed, and allRunning 'nvm use …'fast tests pass insh,bash, andzsh.Running 'nvm use system' should work as expectedfails on my machine, but fails identically on unmodified master (I have no system node installed), so it's unrelated to this change.kshlocally: macOS ships ksh93, which has nolocal, so the existing tests fail there as well. CI should cover it.Manual check: