久しぶりにzshの環境をいじったら起動が重くなったので改善したメモ。
これらの対策+なんでもzcompileでtime zsh -i -c exitが0.7秒から0.17秒になりなんとか許容できるぐらいになった。
brew file wrapper
マニュアルには.zshrcに
if [ -f $(brew --prefix)/etc/brew-wrap ];then
source $(brew --prefix)/etc/brew-wrap
fi
と書けとあるんでそのままコピペしたけど、実はbrew --prefixは結構時間がかかる。そんなに変わるものでもないので/usr/local決め打ちに書き直した。
zplug
プロファイラーで調べて簡単に直せそうなところからいじってみた。
compinit
compinitが結構時間かかるんだけど、よく調べたら.zplug/base/core/core.zshと.zplug/base/core/load.zshの2回呼ばれていて(他にgoogle cloud sdkでもさらに1回ともともと自分の.zshrcの中にあったもう1回の計4回)、なんとなく無駄っぽいから後に呼ばれるload.zshの方のはコメントアウトして見た。何か理由があるのかもしれないけど自分については特に補完がおかしくなるわけでもないのでOKということにしておく。 $fpathの設定を行うプラグインがあることを考慮するとcore.zsh
の方はタイミングが早すぎると思われるのでコメントアウトして様子見。
__zplug::job::handle::flock
flockして混ざらないようにファイルに書く関数があって、ログを書くたびに呼ばれているのだけど、flockがサブシェルを使う書き方になっていた。プロセス終了でロックが自動的に解放されるから解放忘れを気にしなくていい便利な書き方なんだけど、何回も呼ばれるとプロセス生成のオーバーヘッドが積み重なってそれなりの量になる。
(
until zsystem flock -t 3 "$file"
do
# 略
done
# 略
)
以下のようにサブシェルを使わないように書き換え。
until zsystem flock -t 3 -f fd "$file"
do
# 略
done
# 略
zsystem flock -u $fd
__zplug::log::capture::error
プラグインを読み込むところでエラー出力をログに書くために以下のようなことをしています。
{
# Directory '/base/sources' needs to be included in FPATH
autoload -Uz "$val.zsh"
eval "$val.zsh"
unfunction "$val.zsh"
} \
2> >(__zplug::log::capture::error) >/dev/null
パイプを使っているのでプロセス生成のオーバーヘッドがあります。ちゃんとした修正方法は思いついてないのですが、これが必要になるのは不具合があったときで普段は何も出力されない筈なので、自分は起動速度を取ってログ出力部分は削除しました。
__zplug::"io"::file::rm_touch
rm_touchというのが結構上位に来ていて中を見たらこんな感じだった。
__zplug::io::file::rm_touch()
{
local filepath="${argv:?}"
# For shorten the calculation time
if [[ ! -d ${filepath:h} ]]; then
mkdir -p "${filepath:h}"
fi
rm -f "$filepath"
touch "$filepath"
}
rmとtouchは外部コマンドで毎回呼ばれるので時間がかかっていると思われる。しかし、これは結局"$filepath"という空のファイルができればいいだけのような気がするので、以下のように書き換え。
__zplug::io::file::rm_touch()
{
local filepath="${argv:?}"
# For shorten the calculation time
if [[ ! -d ${filepath:h} ]]; then
mkdir -p "${filepath:h}"
fi
: > "$filepath"
}
zplug check
マニュアルには.zshrcに以下のように記述して未インストールのプラグインがあるときはインストールするか聞くようにするといいとあるのだけれど、zplug checkも結構時間がかかります。
if ! zplug check --verbose; then
printf "Install? [y/N]: "
if read -q; then
echo; zplug install
fi
fi
読み込むべきプラグインが増えるのは.zshrcに変化があったときと考えていいと思うので、チェック時刻を保存して.zshrcが新しくなっているときだけこれをするようにしました。
if [ ! ~/.zplug/last_zshrc_check_time -nt ~/.zshrc ]; then
touch ~/.zplug/last_zshrc_check_time
if ! zplug check --verbose; then
printf "Install? [y/N]: "
if read -q; then
echo; zplug install
fi
fi
fi
google-cloud-sdkのcompletion.zsh.inc
zplugのとこでも軽く触れたけどこいつの中でもcompinitしていて無駄だからコメントアウト。