-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
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
takes about a second
#860
Comments
It's very slow for me too. My SSD is a few years old so it is not the latest and greatest, but I guess nvm should not make execution of my bash export NVM_DIR=~/.nvm
time source $(brew --prefix nvm)/nvm.sh This outputs:
|
@behrangsa |
@ljharb Hi Jordan, I hardcoded First load:
Subsequent loads (in new tabs):
So I guess this is more or less inline with @dylanpyle's findings, even though that I've installed |
Thanks, I appreciate that - I doubt installing with brew affects the speed of |
It is |
@behrangsa can you try with |
I just upgraded to
|
thanks - i'll keep looking into it |
Thanks @ljharb! 👍 |
More data: I'm seeing the same issue on a different machine with a similar setup:
Issue is present even with everything non-nvm related removed from zshrc - hopefully ruling out conflicting scripts. |
Until nvm-sh/nvm#860 is solved and nvm.sh is optimized for speed, this will only export the script path, invoking it must be done explicitly. I use this workflow by opening a new shell, and running `source $NVM_SCRIPT`.
Same problem here:
|
@sebicas what's the output of |
@ljharb here is the output
I am using the default osx shell |
Thanks - by chance do you have an SSD, or a standard HDD? |
Standard HDD is a Western Digital Scorpio Blue (750GB WD7500BPVT) just in case. |
Hi, noticing the same problem here. I isolated the lag in my shell loading down to the sourcing of the nvm script.
|
I have "solved" this issue for me the following, pragmatic way in alias node='unalias node npm && nvm use v4.2.1 && node'
alias npm='node -v > /dev/null && npm' # optional This way my shell always starts up fast, and until I need With the second line also |
Note that that workaround will mean all of your globally-installed modules will be unavailable until after you've referenced |
+1 I have the same problem. I use prezto and I don't think the shell or the shell-manager is causing problem.
Prezto zsh without nvm $ time /bin/zsh -i -c exit
/bin/zsh -i -c exit 0.14s user 0.07s system 92% cpu 0.230 total Prezto zsh with nvm $ time /bin/zsh -i -c exit
/bin/zsh -i -c exit 0.57s user 0.10s system 86% cpu 0.781 total Vanilla zsh without nvm $ time /bin/zsh -i -c exit
/bin/zsh -i -c exit 0.01s user 0.00s system 74% cpu 0.016 total Vanilla zsh with nvm $ time /bin/zsh -i -c exit
/bin/zsh -i -c exit 0.52s user 0.08s system 88% cpu 0.676 total nvm.sh seems to be taking 0.5s on average to load up. |
Anecdote: I tracked down my slow shell to nvm as well. I found the following things slow: In my export NVM_DIR=~/.nvm
source `brew --prefix nvm`/nvm.sh Findings:
My two solutions were:
|
@ibash |
Just reinstalled w/o homebrew. You're right, I think what I was seeing was a side effect of blowing away my alias default. |
Same over here
takes edit sourcing is fine if I |
I commented out part of the script for diff --git a/nvm.sh b/nvm.sh
index c6b8f83..0ad90f1 100755
--- a/nvm.sh
+++ b/nvm.sh
@@ -1805,11 +1805,11 @@ nvm() {
# This nvm_ensure_version_installed call can be a performance bottleneck
# on shell startup. Perhaps we can optimize it away or make it faster.
- nvm_ensure_version_installed "$PROVIDED_VERSION"
- EXIT_CODE=$?
- if [ "$EXIT_CODE" != "0" ]; then
- return $EXIT_CODE
- fi
+ # nvm_ensure_version_installed "$PROVIDED_VERSION"
+ # EXIT_CODE=$?
+ # if [ "$EXIT_CODE" != "0" ]; then
+ # return $EXIT_CODE
+ # fi
local NVM_VERSION_DIR
NVM_VERSION_DIR="$(nvm_version_path "$VERSION")"
@@ -1836,28 +1836,28 @@ nvm() {
command rm -f "$NVM_DIR/current" && ln -s "$NVM_VERSION_DIR" "$NVM_DIR/current"
fi
local NVM_USE_OUTPUT
- if nvm_is_iojs_version "$VERSION"; then
- if [ $NVM_USE_SILENT -ne 1 ]; then
- NVM_USE_OUTPUT="Now using io.js $(nvm_strip_iojs_prefix "$VERSION")$(nvm_print_npm_version)"
- fi
- else
- if [ $NVM_USE_SILENT -ne 1 ]; then
- NVM_USE_OUTPUT="Now using node $VERSION$(nvm_print_npm_version)"
- fi
- fi
- if [ "_$VERSION" != "_system" ]; then
- local NVM_USE_CMD
- NVM_USE_CMD="nvm use --delete-prefix"
- if [ -n "$PROVIDED_VERSION" ]; then
- NVM_USE_CMD="$NVM_USE_CMD $VERSION"
- fi
- if [ $NVM_USE_SILENT -eq 1 ]; then
- NVM_USE_CMD="$NVM_USE_CMD --silent"
- fi
- if ! nvm_die_on_prefix "$NVM_DELETE_PREFIX" "$NVM_USE_CMD"; then
- return 11
- fi
- fi
+ # if nvm_is_iojs_version "$VERSION"; then
+ # if [ $NVM_USE_SILENT -ne 1 ]; then
+ # NVM_USE_OUTPUT="Now using io.js $(nvm_strip_iojs_prefix "$VERSION")$(nvm_print_npm_version)"
+ # fi
+ # else
+ # if [ $NVM_USE_SILENT -ne 1 ]; then
+ # NVM_USE_OUTPUT="Now using node $VERSION$(nvm_print_npm_version)"
+ # fi
+ # fi
+ # if [ "_$VERSION" != "_system" ]; then
+ # local NVM_USE_CMD
+ # NVM_USE_CMD="nvm use --delete-prefix"
+ # if [ -n "$PROVIDED_VERSION" ]; then
+ # NVM_USE_CMD="$NVM_USE_CMD $VERSION"
+ # fi
+ # if [ $NVM_USE_SILENT -eq 1 ]; then
+ # NVM_USE_CMD="$NVM_USE_CMD --silent"
+ # fi
+ # if ! nvm_die_on_prefix "$NVM_DELETE_PREFIX" "$NVM_USE_CMD"; then
+ # return 11
+ # fi
+ # fi
if [ -n "$NVM_USE_OUTPUT" ]; then
echo "$NVM_USE_OUTPUT"
fi |
@kilianc Thanks - it's likely mostly the |
@ljharb I tried various combinations but everytime I uncomment something it adds between 100 to 300ms. This is pretty slow |
Yes, invoking |
@ljharb I know, but from my perspective I am not going to uncomment those line unless it turns out I broke something :D it's 1s vs 30ms |
I was able to speed up shell init significantly by running
As far as I can tell, for my simple case, this seems to work just as well as |
I totally understand the need to avoid hacky solutions and to cut corners – I guess there are plenty; shells are so versatiles. Would it be reasonable to know what could help improve solve the problem though? What is the path to resolution? 'cause if using nvm decreases the developer experience in the terminal, it defeats the purpose of the tool itself – and nvm is great so it does not deserve to be undermined by this loading performance issue. |
@oncletom very diplomatically said. the main slowdown is |
People who actually read the docs should not suffer - see nvm-sh#860 and nvm-sh#703
Here's a script to lazy load nvm when using bash as your shell: # Set up NVM
# Lazily initialize nvm to keep shell start up time fast.
export NVM_DIR="$HOME/.nvm"
export NVM_SH="$NVM_DIR/nvm.sh"
# https://github.com/creationix/nvm/issues/860
declare -a NODE_GLOBALS=(`find $NVM_DIR/versions/node -maxdepth 3 -type l -wholename '*/bin/*' | xargs -n1 basename | sort | uniq`)
NODE_GLOBALS+=("node")
NODE_GLOBALS+=("nvm")
load_nvm () {
# echo "Loading NVM..."
[ -s "$NVM_SH" ] && source "$NVM_SH"
# echo "Loaded NVM"
}
unhook_nvm_load () {
# echo "Unhooking NVM Lazy Loader"
for cmd in "${NODE_GLOBALS[@]}"; do
unset -f "${cmd}"
done
# echo "Unhooked NVM Lazy Loader"
}
for cmd in "${NODE_GLOBALS[@]}"; do
eval "function ${cmd} () { unhook_nvm_load; load_nvm; ${cmd} \$@; }"
done |
@0xcaff see #860 (comment) (specifically, what if a global is available in one version of node but not another, and i try to use it) |
Good, point. It will fail in that case. I only use |
@ljharb earlier comments suggest that there are corner cases to consider for iojs and older nodejs versions. If a user is no longer interested in those, is there a way to make this script faster? |
@defunctzombie the speed here is 100% unrelated to node or io.js version; as it's solely caused by every version of npm running |
Why does |
@TylerBrock it's not as trivial as you'd think; it merges any |
Ok, fair enough. I might not know enough about the inner workings and capabilities here but why does nvm need to know what npm thinks the prefix is? Can we skip this interrogation altogether? Perhaps we could set some sort of NVM_PATH that gets us the root where we store all the node installations. Then we can get the version of node we want (or default) from the closest nvmrc to the CWD thereby breaking all this down to a simple path concatenation. Example:
export prefix=${NVM_PATH}/versions/node/${NVM_NODE_VERSION} Searching upwards to the find the closest nvmrc should take some time but it shouldn't take 500ms+. Every other verison manager has figured out how to make this operation fast we should be able to do it as well. |
@TylerBrock because if npm's prefix is overridden (from the nvm-managed path), then I agree that it shouldn't be slow; I believe it's because (Also note it's I certainly could just always override the prefix setting; but since it can be set any number of ways, it's much safer to require the user to manually remove the override. |
People who actually read the docs should not suffer - see nvm-sh#860 and nvm-sh#703
@ljharb Maybe this is a terrible idea, but hear me out: For the people who read the docs, perhaps some sort of You see, I'm currently using n to manage my multiple node versions, but I'm not a fan of the way it manages node (i.e. use of At this point, I'm sorely tempted to throw in the towel and just use @AGhost-7's recent patch (AGhost-7@892dbb9), which removes the prefix check entirely. At the same time, however, I'd prefer to use the official |
@caleb531 i'd be all in favor of that, except that the instant there's an official way to bypass the checking, it's going to show up in tweets, blog posts, and SO posts where people just blindly copy-paste it to "get things working". That's not going to ensure that the majority "understand the risks". |
@ljharb Fair enough. Here's another idea: have nvm only check the prefix until it encounters the default prefix (either because the user removed their custom prefix, or if the prefix was never changed in the first place). The logic could work like the following, probably using some file under
Theoretically, you could check the prefix periodically on a certain interval (i.e. if the last check was more than a week ago), but that feels rather arbitrary. I'd rather go with the above approach: checking on installation, update/reinstall, and first invocation of I personally think this is a reasonable approach, though it really depends on how likely the user would change the prefix after they've installed nvm. I suspect that's not very likely, but I'd be curious to hear what anyone else thinks. |
#1679 exhaustively covers all the environment variables that I believe the remaining piece to remove |
Here's my performance hacks, it help |
This comment has been minimized.
This comment has been minimized.
Consider using a fnm. Performances are stellar. |
This comment has been minimized.
This comment has been minimized.
Is the issue closed because it's fixed? @ljharb |
@Rush yes! See the linked PR. v0.37.0 is released with the fix. If you’re still seeing issues after updating and restarting your terminal, please file a new issue and fill out the issue template. |
(Pulling some details out of the thread on #703 per request from @ljharb)
nvm use
is slow. This makes shell startup slow, and switching versions after shell startup slow too.System information:
My temporary solution is as follows:
— then adding this hack in my zshrc
The text was updated successfully, but these errors were encountered: