From dda8bb6165553b17d997df29dcfa663668608178 Mon Sep 17 00:00:00 2001 From: Riatre Foo Date: Tue, 9 Feb 2021 01:14:35 +0800 Subject: [PATCH] Optimize lazy loading performance zsh-nvm is pretty slow to load even with NVM_LAZY_LOAD=1 due to the presence of a lots of global binaries. I have ~110 global binaries installed, zprof shows that `_zsh_nvm_lazy_load` alone takes 113.23ms, causing noticable delay during shell startup. Further profiling shows that when there are a lot of global binaries, running `basename` on each of them (because `xargs -n1`) is pretty slow, the same goal could be achieved via zsh builtin expansion flags or modifiers and it's much faster. Running `which` in a for loop also has a similar but less significant drawback. After the change zsh-nvm loads in 6.03ms under same conditions. Additionally, added proper quoting to guard against binaries with whitespaces in their name. This has near to zero real-world impact but still, it is the correct thing to do. --- zsh-nvm.plugin.zsh | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/zsh-nvm.plugin.zsh b/zsh-nvm.plugin.zsh index d85e94c..226bd96 100644 --- a/zsh-nvm.plugin.zsh +++ b/zsh-nvm.plugin.zsh @@ -22,20 +22,6 @@ _zsh_nvm_install() { $(builtin cd "$NVM_DIR" && git checkout --quiet "$(_zsh_nvm_latest_release_tag)") } -_zsh_nvm_global_binaries() { - - # Look for global binaries - local global_binary_paths="$(echo "$NVM_DIR"/v0*/bin/*(N) "$NVM_DIR"/versions/*/*/bin/*(N))" - - # If we have some, format them - if [[ -n "$global_binary_paths" ]]; then - echo "$NVM_DIR"/v0*/bin/*(N) "$NVM_DIR"/versions/*/*/bin/*(N) | - xargs -n 1 basename | - sort | - uniq - fi -} - _zsh_nvm_load() { # Source nvm (check if `nvm use` should be ran after load) @@ -85,7 +71,7 @@ _zsh_nvm_lazy_load() { if [[ "$NVM_NO_USE" == true ]]; then global_binaries=() else - global_binaries=($(_zsh_nvm_global_binaries)) + global_binaries=("$NVM_DIR"/v0*/bin/*(N:t) "$NVM_DIR"/versions/*/*/bin/*(N:t)) fi # Add yarn lazy loader if it's been installed by something other than npm @@ -95,19 +81,22 @@ _zsh_nvm_lazy_load() { global_binaries+=('nvm') global_binaries+=($NVM_LAZY_LOAD_EXTRA_COMMANDS) + # Deduplicate + typeset -U global_binaries + # Remove any binaries that conflict with current aliases local cmds - cmds=() - for bin in $global_binaries; do - [[ "$(which $bin 2> /dev/null)" = "$bin: aliased to "* ]] || cmds+=($bin) - done + IFS=$'\n' cmds=($(whence -w -- "${global_binaries[@]}" 2> /dev/null)) + unset IFS + cmds=(${cmds#*": alias"}) + cmds=(${(@q-)cmds%": "*}) # Create function for each command for cmd in $cmds; do # When called, unset all lazy loaders, load nvm then run current command eval "$cmd(){ - unset -f $cmds > /dev/null 2>&1 + unset -f ${cmds[@]} > /dev/null 2>&1 _zsh_nvm_load $cmd \"\$@\" }"