-
-
Notifications
You must be signed in to change notification settings - Fork 8.1k
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
nvm very slow to start #2724
Comments
PRs to improve specific slow places are appreciated. This kind of profiling output is also very helpful, since it helps highlight what needs work. |
This comment has been minimized.
This comment has been minimized.
I've done a bit of digging and there seems to be a lot of custom logic (and therefore additional complexity) to support "iojs". I might be being naive, but does anyone even use iojs? Their website looks like it was updated semi-recently, but they seem to mention that nvm doesn't support it yet (when it has for 7 years!):
I've deleted anything pertaining to "iojs" from my Would this project be interested in a PR to remove iojs support? Edit: I just noticed that the link to io.js' repo from nvm's README file just redirects to node's repo now |
The plumbing for that is also needed to support node RCs and nightlies, so even if i wanted to remove it (i don’t - i have 300+ repos that test on it, which constitutes over 10% of npm’s download traffic that benefits from the support) i don’t think it’d end up making things faster since we still want to add RC support in particular. I’d love a PR that made the existing feature set faster, of course :-) |
this plugin makes loading of nvm zsh functions lazy https://github.com/lukechilds/zsh-nvm (on my machine >800ms -> ~40ms) works great and has some interesting options; ... however it has not seen the update for nearly 2 years it would be a good course of action to incorporate the logic from that script into this one |
A lazy loading approach can be used as a work around if you're seeing lag before the prompt becomes usable. The following can be added to your lazy_load_nvm() {
unset -f node nvm
export NVM_DIR=~/.nvm
[[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh"
}
node() {
lazy_load_nvm
node $@
}
nvm() {
lazy_load_nvm
node $@
} |
Thanks for linking this! I ended up needing to make a few changes, if anyone else runs into hiccups: lazy_load_nvm() {
- unset -f node nvm
+ unset -f npm node nvm
export NVM_DIR=~/.nvm
[[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh"
+ [ -s "$NVM_DIR/bash_completion" ] && source "$NVM_DIR/bash_completion"
}
+ npm() {
+ lazy_load_nvm
+ npm $@
+ }
node() {
lazy_load_nvm
node $@
}
nvm() {
lazy_load_nvm
- node $@
+ nvm $@
} |
Note that any lazy loading approach has some caveats; namely that any global packages you have installed won't be available until the first time you run |
The lazy loading approaches don't work for me since I'm using the zsh hook that automatically runs Edit: I just realized this also includes functions for |
That's handy! Can you share how you are doing that? A link perhaps? |
This is my hack in the
|
This comment was marked as spam.
This comment was marked as spam.
If anyone is interested, I have made it so it lazy loads on cmd run. load-nvmrc() {
local node_version="$(nvm version)"
local nvmrc_path="$(nvm_find_nvmrc)"
if [ -n "$nvmrc_path" ]; then
local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")
if [ "$nvmrc_node_version" = "N/A" ]; then
nvm install
elif [ "$nvmrc_node_version" != "$node_version" ]; then
nvm use
fi
elif [ "$node_version" != "$(nvm version default)" ]; then
nvm use default
fi
}
if [ -s "$HOME/.nvm/nvm.sh" ]; then
export NVM_DIR="$HOME/.nvm"
nvm_cmds=(nvm node npm yarn)
for cmd in $nvm_cmds ; do
alias $cmd="unalias $nvm_cmds && unset nvm_cmds && . $NVM_DIR/nvm.sh --no-use && load-nvmrc && $cmd"
done
fi
|
Take into account that the lazy load approach breaks the LSP servers with nvim if nvm is not loaded previously. I have that problem, and running NVM at least one time before opening nvim solve it. |
The main culprit for me was the
It's not perfect, but it retains the majority of nvm's primary features and stops me waiting forever for my shell to resolve. Here's my implementation:
|
Note that nvm doesn’t do that - that’s just in the readme, and something you added yourself. Note that your item 2 will mean you can’t use globally installed npm packages in the default node version until nvm has loaded. |
@ljharb You're correct that it's not supported by the maintainers, but as you say it is the part of the README instructions for the zsh shell. I think it should at least have a warning that it could result in a slow shell, or in an ideal world the example should be replaced entirely. Whether it is officially supported or not is irrelevant if a problematic solution is being signposted to new users as part of the instructions – less "something you added yourself", more "something we suggested". Happy to contribute a PR if useful! Agreed my solution isn't the best (unless you want to add an nvm loader for every globally installed package), but it does the job for me as I don't have any globally installed packages that depend on a specific version of node. Do you have any suggestions on how to fix? |
@lucasjohnston i'm the maintainer, and sure, either one is a great idea. PRs are welcome. No, I don't have any way to avoid fully loading nvm that avoids that caveat, which is the sole reason there's no official mechanism to do that (or better, the sole reason it's not just The Way nvm works) |
I have a slightly modified solution by @linorabolini for bash (you'll need to copy their first part): if [ -s "$HOME/.nvm/nvm.sh" ]; then
export NVM_DIR="$HOME/.nvm"
nvm_cmds=(nvm node npm yarn)
for cmd in "${nvm_cmds[@]}" ; do
alias $cmd="echo \"'nvm' loading... It's super slow, hold onto your hat...\" && unalias ${nvm_cmds[*]} && unset nvm_cmds && . $NVM_DIR/nvm.sh --no-use && load-nvmrc && $cmd"
done
fi |
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as resolved.
This comment was marked as resolved.
Thank you @linorabolini for your suggestion. Given that |
I just wanted to share that since this issue I've long since switched to mise and it's very performant, and is essentially a drop-in replacement for nvm (for my purposes anyway) |
Sounds like this should be closed. If anyone's still having performance issues with the latest version of nvm, please file a new issue. If you're having trouble with the unsupported snippets in the readme, a PR to improve them would be most welcome. |
For anyone else finding this after reading the blog posts lately about measuring ZHS startup times: My shell took just over 300ms to start, as measured by hyperfine. I commented out the nvm part and it dropped down to around 45ms. I googled around and found fnm, which seems to be a port of My conclusion: for now I will replace
I'm not sure if this is a "performance issue", so I'm a bit hesitant to open a new issue. ~300ms shell startup is probably fine for a lot of people, and I'm not sure that this could be fixed in nvm without switching to a complied language. But if you think that this can be improved and want any more measurements or insight I'm happy to help! |
yes, advertising other projects in any repo is quite unwelcome, and isn't a workaround for those who wish to keep using the same project. |
I think for those who still want to use And yes, advertising other projects is bad form in these places. Definitely a catch 22 since I can understand the desire to share your success and options, which is appreciated, but it can easily be seen as a slap to this project by those who invest such efforts and sacrifices to make it and keep it going... Humans are funny things. Anyway, thanks to the developers of this project for your passion and sacrifice for such a tool. |
This comment was marked as resolved.
This comment was marked as resolved.
I have just installed NVM on a new Windows 11 laptop to use it with Git Bash and WSL. I honestly envy all the commentators above since you are fighting for a sub-second speed improvement. For me, it takes 10 seconds to start NVM.
Output on session start: |
@lashchev nvm-windows is an entirely different project, and I'm pretty sure doesn't use nvm.sh at all. Some of it is just that Windows is slow. inherently. Yes, if you can file a new issue with a fully filled out template, I'd love to address it - however, I don't use Windows, so it's difficult for me to do anything myself (altho i can review a PR and test it on a local vm) |
Rationale: nvm-sh/nvm#2724 Lazy loading nvm with something like `nvm() { unset -f nvm; source-if-exists ~/.nvm/nvm.sh; nvm $@ }` would be another solution, but it has drawbacks as mentioned in that thread. Drops my bash startup from ~470ms to ~320ms.
for me it's taking about 30 seconds and it's crazy |
Here is my attempt at the lazy loading solution. export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
if [[ -d $NVM_DIR ]]; then
unset_nvm_lazy_path() {
export PATH=$(echo $PATH | sed "s|${NVM_LAZY_PATH}:||" )
unset NVM_LAZY_PATH
}
set_nvm_lazy_path() {
unset_nvm_lazy_path
export NVM_LAZY_PATH="$1"
export path=($NVM_LAZY_PATH $path)
}
nvm_lazy_load() {
unset -f nvm
echo "Loading NVM"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
unset_nvm_lazy_path
add-zsh-hook -d chpwd check_for_nvmrc
unset check_for_nvmrc
}
function get_node_dir() {
local target_ver=${1:-$(cat "$NVM_DIR/alias/default")}
target_ver=$(echo $target_ver | sed s/v//)
local version="$(find $NVM_DIR/versions/node -maxdepth 1 -exec basename {} \; \
| sed s/v// \
| grep $target_ver \
| sort --version-sort --reverse)"
[[ -n $version ]] && echo "$NVM_DIR/versions/node/v$version/bin"
}
function nvm() {
nvm_lazy_load
nvm $@
}
function check_for_nvmrc() {
local dir="$PWD"
# Look for .nvmrc file in current directory and parent directories
while [[ -n "$dir" && ! -f "$dir/.nvmrc" ]]; do
dir="${dir%/*}"
done
if [[ -z "$dir" ]]; then
return
fi
local target_ver="$(get_node_dir $(cat "$dir/.nvmrc"))"
if [[ -n $target_ver ]]; then
set_nvm_lazy_path $target_ver
else
nvm_lazy_load
nvm use
fi
}
set_nvm_lazy_path "$(get_node_dir)"
add-zsh-hook chpwd check_for_nvmrc
fi
|
This comment was marked as spam.
This comment was marked as spam.
My solution is to use a function that when first called will be replaced by nvm: # NVM
function nvm ()
{
unfunction nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
nvm $@
} The first time you call |
@wjohnsto that also will prevent |
At this point I just use |
This comment has been minimized.
This comment has been minimized.
True, depending upon what you need this may not work for you. |
Operating system and version:
nvm debug
output:nvm ls
output:How did you install
nvm
?The bash script from the README. I also have the zsh shell extension from the README to automatically run
nvm use
on each directory change.What steps did you perform?
Create a new iTerm tab or pane
What happened?
It's very slow to start every time
I've followed these steps to get some zsh profiling output, this is what it looks like:
What did you expect to happen?
I expected it to load faster
Is there anything in any of your profile files that modifies the
PATH
?There's a few things being added for android development,
ANDROID_HOME
,JAVA_HOME
, etcThe text was updated successfully, but these errors were encountered: