Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance: nvm use default slow, slows down shell startup (nvm.sh) #703

Closed
joliss opened this issue Mar 26, 2015 · 23 comments
Closed

Performance: nvm use default slow, slows down shell startup (nvm.sh) #703

joliss opened this issue Mar 26, 2015 · 23 comments
Assignees
Labels
performance This relates to anything regarding the speed of using nvm.

Comments

@joliss
Copy link
Contributor

joliss commented Mar 26, 2015

. ~/.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?

@joliss
Copy link
Contributor Author

joliss commented Mar 26, 2015

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

@ljharb
Copy link
Member

ljharb commented Mar 26, 2015

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.

@joliss
Copy link
Contributor Author

joliss commented Mar 27, 2015

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/null if 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 every nvm use after 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. :)

@ljharb
Copy link
Member

ljharb commented Mar 27, 2015

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.

@ljharb ljharb self-assigned this Mar 27, 2015
joliss added a commit to joliss/nvm that referenced this issue Mar 27, 2015
joliss added a commit to joliss/nvm that referenced this issue Mar 27, 2015
@joliss
Copy link
Contributor Author

joliss commented Mar 27, 2015

Sure: #705

@cesarandreu
Copy link

Awesome! This speed boost makes a huge difference.

@ljharb ljharb closed this as completed in 609d9ee Apr 2, 2015
ljharb added a commit that referenced this issue Apr 2, 2015
Improve startup performance. Closes #703
@AlexKvazos
Copy link

Still takes almost a second for me to startup. If I remove the . ~/.nvm/nvm.sh my shell loads near instantly..

@ljharb
Copy link
Member

ljharb commented Jun 3, 2015

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.

@AlexKvazos
Copy link

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

@ljharb
Copy link
Member

ljharb commented Jun 3, 2015

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?

@AlexKvazos
Copy link

Yeah my bad, I fixed the second link. Not sure how I can make it so that zsh sources once in all cases though.

@AlexKvazos
Copy link

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.

@dylanpyle
Copy link

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

@ljharb
Copy link
Member

ljharb commented Oct 5, 2015

@dylanpyle Are you using oh-my-zsh? What's your output of nvm debug? If you nvm unalias default, does the slowdown disappear?

@dylanpyle
Copy link

@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.

@ljharb
Copy link
Member

ljharb commented Oct 6, 2015

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?

@dylanpyle
Copy link

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

@ljharb
Copy link
Member

ljharb commented Oct 6, 2015

@dylanpyle thanks - and to confirm as well, nvm use 0.10 is not slow? so nvm alias foo is the slow part?

@dylanpyle
Copy link

@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?

@ljharb
Copy link
Member

ljharb commented Oct 6, 2015

@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.

@dylanpyle
Copy link

done: #860

@ljharb ljharb added the performance This relates to anything regarding the speed of using nvm. label Oct 11, 2015
AGhost-7 added a commit to AGhost-7/nvm that referenced this issue Apr 18, 2017
People who actually read the docs should not suffer - see nvm-sh#860 and nvm-sh#703
AGhost-7 added a commit to AGhost-7/nvm that referenced this issue Aug 18, 2017
People who actually read the docs should not suffer - see nvm-sh#860 and nvm-sh#703
@tony
Copy link

tony commented Apr 22, 2018

~/.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

@mrwillis
Copy link

mrwillis commented May 8, 2018

I have the same issue. It is quite slow on Ubuntu 16.04

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance This relates to anything regarding the speed of using nvm.
Projects
None yet
Development

No branches or pull requests

7 participants