Asdf: Slow shell prompt (bash, zsh, fish) w/ Homebrew (macOS)

Created on 9 Aug 2020  路  13Comments  路  Source: asdf-vm/asdf

I'm on macOS Catalina, but I don't believe the version matters here as the issue would likely apply only to those that are using Homebrew. I've had the following issue for a long time and was finally fed up to the point that I began to search for the culprit. This may help someone, so I'd like to update the documentation located at https://asdf-vm.com/#/core-manage-asdf-vm?id=install, but the guide doesn't describe how this can be done

I'm using bash, but I think this, too, applies to Fish and Zsh users -- anyone using Homebrew

Issue

It takes a good couple of seconds before my shell prompt is loaded and ready for action. By process of deduction, I discovered that asking Hombrew to find the prefix for a given utility, asdf in this case, took anywhere from 2-3 seconds. This would be extremely bothersome for anyone using multiple tabs or even a terminal multiplexer. The documentation asks us to add the following to our .bash_profile:

. $(brew --prefix asdf)/asdf.sh
. $(brew --prefix asdf)/etc/bash_completion.d/asdf.bash

Solution

Easy - hard-code the Homebrew prefix in a local bash variable or environment variable:

BREW_PREFIX=/usr/local/opt
. $BREW_PREFIX/asdf/asdf.sh
. $BREW_PREFIX/asdf/etc/bash_completion.d/asdf.bash

Less easy - try to speed up Homebrew's prefix option and resolution upstream

Most helpful comment

Why not simply change the instructions to

echo -e "\n. $(brew --prefix asdf)/asdf.sh" >> ~/.bashrc

or so? The brew --prefix asdf part will be computed when writing to the settings file and not during startup, which will resolve this issue.
Important point: the asdf.sh path is consistent no matter the version of asdf, so it would work with any setup and would not break brew upgrade.
The only case where it would be an issue is if the user changes his Homebrew directory or if the person maintaining the Homebrew package for asdf decides to make a breaking change.
Overall, I think the benefits of a fast shell startup overweight the potential issues it could cause, which really seem to be unlikely enough.

All 13 comments

I'm unfamiliar with how brew --prefix works, but given there's a command to find it is it possible it can change? If the asdf Homebrew package gets updated with a different install location and Brew updates all it's packages, then would this break people's systems?

I have Homebrew on one system, though I barely use brew and have not experienced this. Is brew --prefix affected by the number of packages installed with Homebrew?

A quick Google landed me here: https://stackoverflow.com/questions/24377639/can-i-change-homebrews-prefix Which references HOMEBREW_PREFIX during Homebrew installation. Is this value available in your shell after initializing Homebrew? Can it be used instead?

@jthegedus valid questions. I guess I wasn't as clear as I thought

$HOMEBREW_PREFIX is set by Homebrew and it appears that Homebrew provides a utility function to apply that prefix to any installed utility, like asdf via $(brew --prefix asdf), but as noted -- incredibly slow

It wasn't clear in my recommendation how I came up with what I have:

  1. take the output of $ echo $(brew --prefix asdf)
  2. create a local variable, like BREW_PREFIX and use it as the prefix for both a) asdf.sh and b) asdf.bash

I'm more inclined to recommend this as an optimization in the docs than an explicit installation instructions.

  • as the exact location can potentially vary per Homebrew installation location
  • the installation location of the asdf Homebrew package itself may change location across versions (an assumption, happy to be corrected)

Is performing the command once like so much better:

ASDF_BREW_PREFIX=$(brew --prefix asdf)
. $ASDF_BREW_PREFIX/asdf/asdf.sh
. $ASDF_BREW_PREFIX/asdf/etc/bash_completion.d/asdf.bash

On the surface that should halve the time to init asdf, no?

@jthegedus I can see why. Having it as an optimization recommendation seems valid

I don't think it'll halve the time if you're still relying on Homebrew to generate that prefix (benchmarks below):

# test.sh (your suggestion)

#!/usr/local/bin/bash
ASDF_BREW_PREFIX=$(brew --prefix asdf)
. $ASDF_BREW_PREFIX/asdf.sh
. $ASDF_BREW_PREFIX/etc/bash_completion.d/asdf.bash
$ time ./test.sh

real    0m3.016s
user    0m1.293s
sys     0m0.952s

cost to generate the prefix:

$ time brew --prefix asdf
/usr/local/opt/asdf

real    0m1.946s
user    0m1.138s
sys     0m0.695s

when placed in a variable in test.sh/.bash_profile

$ time ./test.sh

real    0m0.243s
user    0m0.007s
sys     0m0.009s

@wulymammoth Thanks for providing more concrete data of each case. Are you able to confirm if this is a factor of the number of Homebrew packages on the system? Just for extra information in the docs update.

@jthegedus difficult to confirm, but it is certainly an issue and core maintainers seem to be aware of it, even so far as making an attempt to fix it, but gave up (only a week ago) -- https://github.com/Homebrew/brew/issues/8189#issuecomment-667639679

Just for reference, with respect to --prefix, the manual's description follows. My interpretation is that this is likely static, unless otherwise deliberately changed:

   --prefix [formula]
       Display Homebrew's install path. Default: /usr/local on macOS and /home/linuxbrew/.linuxbrew on Linux.

       If formula is provided, display the location in the Cellar where formula is or would be installed.

Why not simply change the instructions to

echo -e "\n. $(brew --prefix asdf)/asdf.sh" >> ~/.bashrc

or so? The brew --prefix asdf part will be computed when writing to the settings file and not during startup, which will resolve this issue.
Important point: the asdf.sh path is consistent no matter the version of asdf, so it would work with any setup and would not break brew upgrade.
The only case where it would be an issue is if the user changes his Homebrew directory or if the person maintaining the Homebrew package for asdf decides to make a breaking change.
Overall, I think the benefits of a fast shell startup overweight the potential issues it could cause, which really seem to be unlikely enough.

@danhper fairly inline with my original recommendation, and I'd imagine those, like myself, that desire to modularize, will know to place the output elsewhere verses redirecting it

We moved away from _executing commands that modified shell configs_ to what _contents should be added to the config_ to allow users to manage their own configs as they are highly custom.

The only case where it would be an issue is if the user changes his Homebrew directory or if the person maintaining the Homebrew package for asdf decides to make a breaking change.

These cases are my concern. Especially since Homebrew updates it's packages whenever, if there was a breaking change with the asdf Homebrew package it would break for everyone at different times.

Going with the consensus 馃憤

@wulymammoth Appreciate the input and detail you went to with this, if you have other feedback for asdf we're always happy to receive it to discuss 馃槃

@jthegedus you bet! I just appreciate that this tool exists and recommend it a lot. Thanks for asking the right questions opening up the doors for me to probe deeper as well :)

Was this page helpful?
0 / 5 - 0 ratings