ShellScript
Bash
Zsh
shell

ログインシェルの起動を高速化する lazyenv を作った

お前のシェル重すぎだろと言われながらも、モッサリとしたシェル環境を使い続けて来たのだが、先日重い腰を上げて高速化した。その時に作った lazyenv を紹介する。

lazyenv とは

任意の処理を、任意のコマンドをトリガーにキックさせることが出来る、シンプルな機能を提供する bash スクリプトです。

どこが高速化できるのか

lazyenv は、ログインシェル起動時に必須ではない処理を遅延させることで、ログインシェルの起動を高速化します。

私の環境では、ログインシェルの起動に要する時間の大半を pyenv が占めていました。

pyenv init が重い

% time (eval "$(pyenv init -)")
( eval "$(pyenv init -)"; )  1.15s user 0.67s system 80% cpu 2.262 total

brew --prefix も地味に重い

% time (brew --prefix pyenv)
/usr/local/opt/pyenv
( brew --prefix pyenv; )  0.50s user 0.22s system 81% cpu 0.876 total

pyenv は python を使う時まで必要ないので、python コマンドを叩くまで遅延させるようにすると、シェルの起動時間は次のように改善します。

before
% time (zsh -i -c exit)
( zsh -i -c exit; )  1.19s user 0.79s system 57% cpu 3.413 total
after
% time (zsh -i -c exit)
( zsh -i -c exit; )  0.11s user 0.08s system 74% cpu 0.246 total

3.413sec → 0.246sec

after の方は、早くなったからと言って、rbenv, jenv, nodenv などの開発環境を追加しています。

使ってみる

~/.zshrc
source /path/to/lazyenv.bash
_pyenv_init() {
    export PYENV_ROOT=`brew --prefix pyenv`
    eval "$(pyenv init -)"
}
eval "$(lazyenv.load _pyenv_init pyenv python pip)"

lazyenv.load は第一引数に、初期化処理の関数名、第二引数以降に初期化処理をフックするコマンド名を与えます。

これは、pyenv, python, pip というコマンドを実行するまで pyenv init の実行を遅延させます。

% time (eval "$(lazyenv.load _pyenv_init pyenv python pip)")
( eval "$(lazyenv.load _pyenv_init pyenv python pip)"; )  0.00s user 0.00s system 78% cpu 0.003 total

圧倒的に高速です。

コマンドリストに shims のリストを与えてもいいと思います。

eval "$(lazyenv.load _pyenv_init pyenv `ls /path/to/pyenv/shims`)"

まとめ

シェルの起動が早くなって、快適生活を送れるようになった。
最近は、全然コード書いてないしサーバーも触ってないけどな!