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

Optimize shell startup with lazy loading? #730

Closed
devinrhode2 opened this issue Apr 17, 2015 · 16 comments · Fixed by #2317
Closed

Optimize shell startup with lazy loading? #730

devinrhode2 opened this issue Apr 17, 2015 · 16 comments · Fixed by #2317
Labels
feature requests I want a new feature in nvm!

Comments

@devinrhode2
Copy link

While playing around with zsh frameworks (I ended up using zgen) I discovered that nvm is the slowest part of my shell startup. I don't actually know bash but somehow made this hack to speed it up, which helped me think of a better mechanism for lazy loading nvm:

  1. Cache the changes nvm makes to your $PATH
    Every time nvm is run, it should re-cache the $PATH segment before exiting. I cached the $PATH segment into a self-contained shell script, named use_cached_nvm_bins.sh, but maybe symlinks could be used instead of caching to a file.
  2. Lazy load nvm
    nvm.sh would be reduced to a very small file that prepends the cached node binary path to your $PATH and only loads the bulk of the code when nvm is invoked. In my hack I was so lazy I didn't even load nvm, and wrote a load_nvm function instead.
@ljharb
Copy link
Member

ljharb commented Apr 17, 2015

This is related to/a duplicate of #709.

Can you elaborate on option 1? I'm not sure what benefit this would offer, as the PATH might be different each time you load a shell, or nvm use.

As for option 2, while you certainly could do something like this:

nvm() {
  [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
  nvm $@
}

… the complexity of adding that to the install script, which already has issues even adding the single "source" line (see https://github.com/creationix/nvm/labels/installing%3A%20profile%20detection), worries me a lot.

@ljharb ljharb added the needs followup We need some info or action from whoever filed this issue/PR. label Apr 17, 2015
@devinrhode2
Copy link
Author

Why would the PATH be different each time you load a shell? After each call to nvm use this cache would need to be updated. Sounds like nvm needs some work, more test coverage, etc.

  1. This doesn't really have anything to do with the install script. We would still only add the one source line for nvm.sh. Rather, nvm.sh itself would be reduced down to something like to code you wrote, except it'd be like:
nvm() {
  [ -s "$NVM_DIR/nvm_CORE.sh" ] && . "$NVM_DIR/nvm_CORE.sh" # This loads nvm
  nvm $@
}

@ljharb
Copy link
Member

ljharb commented Apr 17, 2015

I have multiple shells open at once, and I could easily change the PATH command in my shell profile after loading one shell tab, but before opening another one. nvm is designed to be used in multiple shells at once so any "cache" would have to be per-shell-session - which is what $PATH already is.

@devinrhode2
Copy link
Author

That's a good caveat to this design.

@ljharb
Copy link
Member

ljharb commented Apr 17, 2015

I'll leave this open as a "lazy load" feature request, for sure.

@ljharb ljharb added feature requests I want a new feature in nvm! and removed needs followup We need some info or action from whoever filed this issue/PR. labels Apr 17, 2015
@ljharb ljharb changed the title Optimize shell startup with lazy loading and PATH segment caching? Optimize shell startup with lazy loading? Apr 17, 2015
@devinrhode2
Copy link
Author

@SimenB
Copy link

SimenB commented Jun 16, 2016

Hey, lazy loading nvm in this way drops startup for new shells from a second to half a second, which is great! But npm is not defined until nvm is sourced, so I end up doing nvm ls or something similar before I can run any npm command.

Suggestions on how to source nvm under the hood for npm commands as well? (as you can probably tell, my shell (or zsh in this case) skills are nonexistent)

@SimenB
Copy link

SimenB commented Jun 18, 2016

I added this function, which seems to work well enough 😄

Suggestions appreciated!

@ljharb
Copy link
Member

ljharb commented Jun 18, 2016

That approach will still only work for whichever things you hardcode - node, npm, etc - but will not work for any global modules you have installed in a generic fashion.

@SimenB
Copy link

SimenB commented Jun 18, 2016

node and npm are the only two commands I run globally often, the only other thing I have installed globally is typings, which is run very rarely, so that's no problem!

And as it halves the time it takes to open a new shell, I think it's worth it. Duplicating that sort of function isn't much work if I need to either.
But that's still the "suggested" way to load nvm lazily?

@ljharb
Copy link
Member

ljharb commented Jun 18, 2016

Officially the suggestion is to not load nvm lazily, and to either tolerate the time it takes to load, or write me a PR to make it faster ;-)

However, the approach in your example is fine if you are aware of the caveats, and if you'll remember that you've done that when debugging any issues that pop up in the future.

@devinrhode2
Copy link
Author

SimenB my load_nvm function is pretty fragile but it basically does what you're looking for, it caches the paths to the loaded npm and node binaries by writing them to a file, and then I have that file sourced in my zshrc, so then future shells get npm and node added to the PATH without loading nvm. It's really broken because, like you, I don't know bash.. I just hacked together some snippits from SO.. But it works and can be improved by learning a wee bit of bash..

@carlesba
Copy link

carlesba commented Jul 6, 2016

is there any final solution?

@ljharb
Copy link
Member

ljharb commented Jul 6, 2016

@carlesba #730 (comment)

@lukechilds
Copy link
Contributor

For anyone here using zsh interested in lazy loading I've just added support for lazy loading in zsh-nvm: https://github.com/lukechilds/zsh-nvm#lazy-loading

I'm getting about 70x faster startup times (874ms down to 12ms)

@bakyeono
Copy link

lukechilds' plugin is cool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature requests I want a new feature in nvm!
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants