zshrcの中でbrew --prefixしないほうがよい理由


zshrcとかbashrcの中で brew --prefix foo しない方がよいです。理由はめちゃくちゃ遅いからです。

3行で説明

  • brew --prefix なんとか は2017年版MacBookProでも0.8秒くらいかかる
  • 速度が重要な場面では絶対パスをべた書きする方がよい
  • homebrew開発元も認識してはいるが、2018.8現時点では未解決

brew --prefix なんとか はすごく遅い

自分の環境でzshの起動がやたら遅いので原因を調べたところ、 brew --prefix coreutils が原因であることがわかりました。

試しに単体で実行してみると、確かに 0.88秒かかっています。

~  time brew --prefix coreutils
/usr/local/opt/coreutils
brew --prefix coreutils  0.48s user 0.21s system 77% cpu 0.880 total

しかも自分の場合は以下のように2回呼んでいたので合計1.7秒この処理に費やされていました。

export PATH="$(brew --prefix coreutils)/libexec/gnubin:$PATH"
export MANPATH="$(brew --prefix coreutils)/libexec/gnuman:$MANPATH"

brew --prefixの値なんてそうそう変わるものではないし自分はデフォルト設定のまま変更していないので、 パス直書きに変更してみたところ、zshの起動が1.7秒短縮されました。

-    export PATH="$(brew --prefix coreutils)/libexec/gnubin:$PATH"
-    export MANPATH="$(brew --prefix coreutils)/libexec/gnuman:$MANPATH"
+    export PATH=/usr/local/opt/coreutils/libexec/gnubin:$PATH"
+    export MANPATH=/usr/local/opt/coreutils/libexec/gnuman:$MANPATH"

ちなみに brew --prefix パッケージ名 が遅いのは coreutils に限らずどんなパッケージ名を指定しても遅いようです。

$ time brew --prefix go
/usr/local/opt/go
brew --prefix go  0.48s user 0.20s system 75% cpu 0.909 total
$ time brew --prefix sl
/usr/local/opt/sl
brew --prefix sl  0.48s user 0.21s system 73% cpu 0.928 total

パッケージ指定なしの brew --prefix もやや遅い

$ time brew --prefix
/usr/local
brew --prefix  0.02s user 0.02s system 59% cpu 0.074 total

この用途なら whichコマンドを使う方が速い。

$ time dirname $(dirname $(which brew))
/usr/local
dirname $(dirname $(which brew))  0.00s user 0.00s system 47% cpu 0.008 total

しかしzshrcとかに書く用途なら、動的に取得する必要性もそれほどないのでやはりパス名をべた書きするのが一番シンプルかつ高速でよいと思いました。

HomebrewにIssueが上がっている

ちなみに brew --prefix なんとか が遅い件は homebrew本体にもissueがあがっているので開発元も認識していはいるようです。

要約すると、

  • バグではない
  • 簡単には直せない。PRはウェルカム
  • $(which brew) を使うほうが速い

とのことです。