. ~/.nvm/nvm.sh adds about half a second to shell startup. The main culprits seem to be nvm ls default and nvm use default - commenting them out drops the timing reported by time . ~/.nvm/nvm.sh to near-zero.
I wonder if we can speed those up, or replace them with a cheaper operation for shell startup?
OK, I think I identified most of the places that cause slowdown - got it down to .05 seconds by putting in some hacks. I'm not suggesting you apply these hacks, but just wanted to demonstrate that it should be possible in principle to get fast startup.
VERSION="$(nvm_version "$PROVIDED_VERSION")" is slow, but there seems to be no need for it to be so slow. Adding a quick hack above the else speeds it up:
@@ -1307,6 +1307,8 @@ nvm() {
PROVIDED_VERSION="$NVM_RC_VERSION"
VERSION="$(nvm_version "$PROVIDED_VERSION")"
fi
+ elif [ "$2" == default ]; then # performance
+ VERSION="$(< ~/.nvm/alias/default)"
else
local NVM_IOJS_PREFIX
NVM_IOJS_PREFIX="$(nvm_iojs_prefix)"
There is a nvm_ensure_version_installed "$PROVIDED_VERSION" call that might be overkill to do on each shell startup. I just took it out for now:
@@ -1347,7 +1349,6 @@ nvm() {
return 8
fi
- nvm_ensure_version_installed "$PROVIDED_VERSION"
EXIT_CODE=$?
if [ "$EXIT_CODE" != "0" ]; then
return $EXIT_CODE
And finally checking for the presence of a default installation (nvm ls default) could be as easy as checking for file presence:
@@ -1718,7 +1719,7 @@ if nvm_supports_source_options && [ "_$1" = "_--install" ]; then
elif nvm_rc_version >/dev/null 2>&1; then
nvm install >/dev/null
fi
-elif nvm ls default >/dev/null; then
+elif [ -f ~/.nvm/alias/default ]; then
nvm use default >/dev/null
elif nvm_rc_version >/dev/null 2>&1; then
nvm use >/dev/null
Thanks for researching this!
Of these three optimizations:
I'm not opposed to the first "else" check, but the $(< …) syntax concerns me re portability, and I'd definitely prefer to use nvm_alias default 2> /dev/null rather than hardcoding paths etc. Could you verify that using VERSION="$(nvm_alias default 2> /dev/null)" provides a similar performance bump?
The second can't happen - that's inside nvm use, so even if it's not required on initial sourcing, it's required on every nvm use after that.
As for the third one - I'd be fine switching that line to nvm_alias default 2>&1 >/dev/null if that would provide a similar performance enhancement - could you verify?
In summary, I definitely want performance to improve! However, nvm is sufficiently complex that maintainability trumps performance, so there's only so much optimization I'll be comfortable applying in that regard. Thanks again for doing this, it really helps me to know where specific bottlenecks are.
Could you verify that using
VERSION="$(nvm_alias default 2> /dev/null)"provides a similar performance bump?
Yes, it does - perfect.
As for the third one - I'd be fine switching that line to
nvm_alias default 2>&1 >/dev/nullif that would provide a similar performance enhancement - could you verify?
Yes, it does. (Nitpick: I think it needs to be nvm_alias default >/dev/null 2>&1 for the redirect to work.)
The second can't happen - that's inside
nvm use, so even if it's not required on initial sourcing, it's required on everynvm useafter that.
Right. Maybe there's some way to have a separate (faster) code path for initial sourcing, but I understand that you want things to stay maintainable. :)
Awesome! Would you like to prepare a PR for those 2 changes? If not, I'll take care of it, but I don't want to steal your thunder.
Sure: #705
Awesome! This speed boost makes a huge difference.
Still takes almost a second for me to startup. If I remove the . ~/.nvm/nvm.sh my shell loads near instantly..
There's still work to be done here, clearly.
The odd thing is that it's lightning fast on my Mac(s), but enough people have had this issue that it's probably something in my environment allowing it to be fast, not something in yours making it slow.
My problem is also that I had to add that both to my .zshrc and .zprofile for nvm to work on my terminal and for sublime plugins to be able to use node. this makes the startup time twice the normal it has to be.
.zprofile: http://puu.sh/ibneI/065bcb95e0.png
then..
.zshrc: http://puu.sh/ibnnR/f13cb0f2ac.png
Those are the same link.
But also, presumably there's a better way to set up the profile files so that's not necessary? ie, a file that zsh sources once in all cases?
Yeah my bad, I fixed the second link. Not sure how I can make it so that zsh sources once in all cases though.
i was able to set a custom path for node on my sublime plugin. Now I am only running the shell script once on shell startup. This still has a ~.5 second startup time though.
Anecdotally: I'm seeing a consistent 0.93 - 1.5 second slowdown on every launch.
nvm 0.28.0
zsh 5.0.8
osx 10.10.5
@dylanpyle Are you using oh-my-zsh? What's your output of nvm debug? If you nvm unalias default, does the slowdown disappear?
@ljharb not using oh-my-zsh.
λ nvm debug
$SHELL: /bin/zsh
$NVM_DIR: '$HOME/.nvm'
$PREFIX: ''
$NPM_CONFIG_PREFIX: ''
nvm current: v0.10.38
which node: $NVM_DIR/v0.10.38/bin/node
which iojs: iojs not found
which npm: $NVM_DIR/v0.10.38/bin/npm
npm config get prefix: $NVM_DIR/v0.10.38
npm root -g: $NVM_DIR/v0.10.38/lib/node_modules
If you nvm unalias default, does the slowdown disappear?
Yep, looks like it! Seems like I can just stick something like:
export PATH=/Users/dylan/.nvm/v0.10.38/bin/:$PATH
in my zshrc, and an nvm used version will take priority over that if specified. Seems to defeat the purpose a little bit, but suits my immediate needs — and no more slowdown.
Certainly you can hardcode it, but it shouldn't be necessary :-( if you do nvm alias foo 0.10.38, and then add nvm use foo instead of the PATH line in your zshrc, is it still slow?
is it still slow?
Yep :(
λ time (nvm use foo)
Now using node v0.10.38 (npm v1.4.28)
( nvm use foo; ) 0.51s user 0.20s system 85% cpu 0.837 total
@dylanpyle thanks - and to confirm as well, nvm use 0.10 is not slow? so nvm alias foo is the slow part?
@ljharb aha, good question. nvm use is indeed the bottleneck:
λ time (nvm use 0.10) develop 13:50
Now using node v0.10.38 (npm v1.4.28)
( nvm use 0.10; ) 0.50s user 0.20s system 83% cpu 0.846 total
λ time (nvm use 4) develop 13:50
Now using node v4.1.2 (npm v2.14.4)
( nvm use 4; ) 0.72s user 0.23s system 86% cpu 1.089 total
If this is a separate issue than the parent, want me to open a new one?
@dylanpyle please do open a new one with this timing info - I think it's the same issue but let's start with a fresh context.
done: #860
~/.nvm tags/v0.33.9
❯ zsh --version
zsh 5.5.1 (x86_64-apple-darwin17.5.0)
With / Without [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm:
❯ for i in $(seq 1 5); do /usr/bin/time zsh -i -c exit; done
1.00 real 0.58 user 0.46 sys
1.00 real 0.59 user 0.46 sys
0.99 real 0.59 user 0.46 sys
1.01 real 0.59 user 0.47 sys
0.99 real 0.59 user 0.46 sys
❯ for i in $(seq 1 5); do /usr/bin/time zsh -i -c exit; done
0.14 real 0.09 user 0.04 sys
0.14 real 0.09 user 0.04 sys
0.14 real 0.09 user 0.04 sys
0.13 real 0.09 user 0.04 sys
0.13 real 0.09 user 0.04 sys
I have the same issue. It is quite slow on Ubuntu 16.04
Most helpful comment
@dylanpyle Are you using
oh-my-zsh? What's your output ofnvm debug? If younvm unalias default, does the slowdown disappear?