-
-
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
Performance issues #709
Comments
This is just to write up my findings in case they're helpful for someone who wants to tackle performance; feel free to close whenever. |
Thanks so much for researching this and writing it up! As you acknowledged, I'll look into what can be done. Memoizing "has system node" and "has system iojs" makes sense per-command-invocation, but I wouldn't want to memoize it for the entire shell session. |
I'm surprised that sh/dash is actually used widely enough in practice for nvm to support it, lol. So |
|
…n to avoid a second default alias lookup in `nvm use default`. Related to #709.
POSIX-compliant per http://stackoverflow.com/a/25536935/632724 Relates to #709
@joliss I've added a couple commits to reduce external calls using POSIX parameter filtering. Still looking into some of the other comments. |
@ljharb I pulled in your changes and it lowered my startup time from 320ms total to 190ms total. Nice speed boost! 👍 |
Hooray! Thanks should go to @joliss for the impetus, and majority of the work. |
So much faster, thanks @ljharb! |
@ljharb I'm still digging in for more info, but this change triggers a failure in Jenkins when doing a git checkout and trying to source I don't know what the best solution is yet, so just giving you a heads up! |
@banderson Jenkins should absolutely not fail on any function failure for |
@banderson See #721 about the issue you're having. |
@ljharb awesome, thanks so much for following up, that was a huge help in finding a workaround! |
+1 Takes about 1 second to open a new shell for me at the moment. All |
Any workarounds yet?
|
@moander what shell are you using? So far the major workaround has been to not use |
@ljharb I'm using bash on my brand new out of the box macbook :) |
@moander In that case, I'd love to get more info from you - what's |
|
Would it be useful to maybe do shell detection and use the faster features if available? Would help local terminals where startup time is noticed and still work on travis-ci and other places where startup time is less critical. |
@defunctzombie what "faster features" are you thinking of exactly? |
There were some other issue comments about faster features but not in all Basically something to drop the startup time from a pretty visible 1 second |
Yes but what specific things? The concern is precisely that i don't know what in I just need help figuring out what parts can be sped up that way :-) |
Gotcha. Maybe send out a tweet asking for people to poke around? It gets a lot of use so I bet lots of people would have input. |
This will likely get rejected due to the nature of nvm.sh being a one file script, but I think there is some savings to be had by just parsing less shell script. Separating out all the function bodies into files and then only running the individual files on demand in the function. |
@defunctzombie that approach is being considered in #337, and is quite difficult, especially considering #400 is not yet resolved. |
Bash user here (with a rather simple .bashrc):
The timings appear to be similar to the ones reported by @joliss and @moander. |
nvm v0.26.1
|
@ljharb Yes, I get the following load times ( 0.25.4: 0.207s That's a big improvement indeed! |
Awesome! I'm going to leave this open, because |
On ZSH, 0.27.1 is seeing a HUGE regression % git co v0.26.1 |
@DavidSouther since you have git, could you perhaps use |
It appears to degrade pretty fast by the number of versions you have installed. I commonly switch between lots of versions and have accumulated a number of versions due to updates, usually I purge this because I put my own custom builds of node in there (with special version numbers) to be able to switch to them while debugging things. I hadn't done that for a while and was up to 15 versions of node spanning 0.8 -> 5.x and 2 versions of io.js. My boot time for my shell was getting absurdly long, I assumed it was one of my custom scripts but debugging showed nvm taking 0.93s to load on my system. 0.75s if the fs cache was warmed still. I cleaned out all the versions of node I had installed and that time decreased to 0.26s. So folks sharing times should also share how many versions of node they have installed and whether the fs cache would already be hot (such as if you just ran the |
Interesting! I have 35 versions of node/iojs installed (one for every minor) and I've never once run into any speed issues, but I also don't use |
@ljharb I'm using bash. I can double check the version when I get to work tomorrow. |
@ljharb Messing around with this on my system trying to track down why its noticeably slower since upgrading from OS X 10.10 to 10.11. I have zsh installed from homebrew, and I'm using zprezto rather than oh-my-zsh. Unfortunately I don't have any numbers from before the upgrade, it MAY have been just as slow and I didn't notice. Before I started messing around, this is what it looked like: ~/t/zsh_slow_nvm ❯❯❯ time (source /usr/local/opt/nvm/nvm.sh) real 0.86s Curiously, I happened to consider that I have coreutils installed from homebrew, and I'm using the gnu-utilities module in zprezto, which creates shell functions to redirect to the GNU versions of the core utilities (for reference, https://github.com/sorin-ionescu/prezto/blob/master/modules/gnu-utility/init.zsh). Just by unsetting the shell function for [ and echo: ~/t/zsh_slow_nvm ❯❯❯ time (source /usr/local/opt/nvm/nvm.sh) real 0.43s I'm going to see if there are others that specifically impact the performance, as it still loads WAY faster in bash on my system than in zsh, and report back anything else I find. benevolence:zsh_slow_nvm steve$ time source /usr/local/opt/nvm/nvm.sh real 0m0.428s (edit: correct time outputs because I'm silly) |
@mcm: |
So it turns out, I was reading the time outputs wrong (and doing wrong stuff in general going back and forth between zsh and bash). The time is very similar between bash and zsh when NOT calling the ZSH function for [ and echo. I will install from the curl script and let you know if this changes it without overriding those functions. |
@ljharb Ok, so I ran it all of the various combinations to see what was the fastest. I'm curious why the time difference when installed via homebrew vs curl but if homebrew is unsupported, doesn't matter to me, I'll go with the supported option from here. Either way, the gnu-utilities definitely impacts performance, whether installed via homebrew or curl. It causes less of a difference in shell startup time than actually running commands like "nvm ls", where its definitely noticeable (I actually see "nvm ls" output each line individually when the GNU utilities are enabled). I wonder how many people with oh-my-zsh are using the GNU utilities as well, or if it sets up similar functions, or anything along those lines that is causing their issues. With those disabled, ZSH becomes comparable to bash for all uses. ZSH:
BASH:
|
Thanks, I really appreciate the legwork. |
No problem, glad to help. My last note, if I set a function in bash to use the g[ binary from coreutils, rather than the shell builtin, I get the same slowdown in bash that I do in ZSH. |
After Investigating a bit, I found out that they are two parts that are taking a lot of time : nvm use 5 takes about 700ms on my machine, with hot cache. I found out two lines of the code that together take up for 650ms. First is the
|
@netei Thanks for the research!
|
nvm takes at least 3 seconds to start up for me in bash which seems a lot higher than other times I see here 😢 I'm on a 2011 MacBook that generally performs pretty well. Does anyone have any tips on what might be wrong with my system? |
I've spent some time digging into
nvm.sh
, and found the following performance bottlenecks that affect shell startup (all percentages relative to total shell startup time, 100%):A major source of slowdown seems to be
nvm_ls
; it is called 3 times on startup asnvm_ls default
(plus 3 times recursively, asnvm_ls iojs
here).time nvm_ls default
takes 25%, so the threenvm_ls default
calls account for 75% of the time.Each
nvm_ls
call loses some time onnvm_has_system_node
ornvm_has_system_iojs
(6% each). These calls seem unnecesarily slow because of thedeactivate
in a subshell; I wonder if we can check for system Node and iojs once at the very beginning, before nvm is set up, and just memoize it.There are also a bunch of calls to external commands (like here or here) sprinkled about, which each lose a small amount of time (around 1%) but add up. A big offender is this chain as well. With Bash, it's possible to use built-in functions to avoid these calls: For example, we can use
[[ "$1" =~ ^iojs- ]]
to test for aniojs-
prefix (ref) instead of usinggrep
orcut
, or usePATTERN="${PATTERN#iojs-}"
to strip said prefix (ref) instead of usingsed
. I use these built-ins a lot when I write fast functions, but I'm not well-versed enough in cross-shell scripting to dare attempting to make a pull request for this.The text was updated successfully, but these errors were encountered: