zsh/prezto 高速化メモ
zshの起動時間を計測する
timeコマンドで計測できるが、1回だけの実行では計測結果にバラツキがある。
N回実行した平均を求めるシェルスクリプトを書いた。
code:avgtime_zsh.sh
N=${1:-10}
SUM=0
for n in {1..$N}; do
echo Running zsh $n
(time zsh -i -c exit) 2>&1 | awk '{print $11}' | read ttl
SUM=$(echo "${SUM} + ${ttl}" | bc)
done
echo
AVG=$(echo "scale=3; ${SUM}/${N}" | bc)
echo "Average: ${AVG}"
引数なしで10回の平均値を取る。第一引数で実行回数を指定する
高速化前の起動時間
code:zsh
$ ./avgtime_zsh.sh
...
Average: 1.250
起動時間は1.2秒ほど
zprofでプロファイリングする
~/.zshenvの先頭に
code:.zshenv
zmodload zsh/zprof
を追加
~/.zshrcの末尾に
code:.zshrc
if type zprof > /dev/null 2>&1; then
zprof | cat
fi
を追加
シェルを新たに起動するとプロファイル結果が出る
高速化前のプロファイル結果
code:zprof
num calls time self name
-----------------------------------------------------------------------------------
1) 1 576.79 576.79 49.80% 576.64 576.64 49.79% nvm_die_on_prefix
2) 1 1004.28 1004.28 86.71% 166.19 166.19 14.35% nvm_auto
3) 2 838.09 419.04 72.36% 162.99 81.49 14.07% nvm
4) 1 98.16 98.16 8.48% 87.23 87.23 7.53% nvm_ensure_version_installed
5) 2 40.48 20.24 3.50% 40.48 20.24 3.50% compaudit
6) 3 98.87 32.96 8.54% 40.17 13.39 3.47% pmodload
7) 1 17.45 17.45 1.51% 16.68 16.68 1.44% _zsh_highlight_load_highlighters
8) 2 53.20 26.60 4.59% 12.72 6.36 1.10% compinit
9) 1 10.93 10.93 0.94% 10.93 10.93 0.94% nvm_is_version_installed
10) 2 7.92 3.96 0.68% 7.92 3.96 0.68% promptinit
11) 1 7.64 7.64 0.66% 7.64 7.64 0.66% nvm_supports_source_options
12) 1 7.32 7.32 0.63% 7.32 7.32 0.63% prompt_pure_state_setup
13) 1 7.12 7.12 0.62% 7.12 7.12 0.62% _zsh_highlight_bind_widgets
14) 1 3.34 3.34 0.29% 3.34 3.34 0.29% async_init
15) 2 15.68 7.84 1.35% 2.97 1.49 0.26% prompt_pure_setup
16) 13 2.26 0.17 0.20% 2.26 0.17 0.20% (anon)
17) 11 1.89 0.17 0.16% 1.89 0.17 0.16% add-zsh-hook
18) 2 4.56 2.28 0.39% 1.22 0.61 0.11% async
19) 3 0.92 0.31 0.08% 0.92 0.31 0.08% is-at-least
20) 3 0.53 0.18 0.05% 0.47 0.16 0.04% add-zle-hook-widget
21) 3 0.43 0.14 0.04% 0.43 0.14 0.04% nvm_has
22) 1 16.46 16.46 1.42% 0.20 0.20 0.02% set_prompt
23) 1 16.62 16.62 1.44% 0.16 0.16 0.01% prompt
24) 1 0.11 0.11 0.01% 0.11 0.11 0.01% compdef
25) 1 1012.00 1012.00 87.38% 0.09 0.09 0.01% nvm_process_parameters
26) 1 0.07 0.07 0.01% 0.07 0.07 0.01% is-callable
nvmの読み込みが非常に遅いのでnvmをやめてnodebrewに変えた
.zshrcでnvm.shを起動している部分を削除して、brew install nodebrewしてnodebrewのパスを.zshrcに追記した
nvmをやめた後の起動時間
code:zsh
$ ./avgtime_zsh.sh
...
Average: .625
半分ほどになった
もう一度プロファイルを見てみる
code:zprof
num calls time self name
-----------------------------------------------------------------------------------
1) 3 126.98 42.33 71.96% 43.41 14.47 24.60% pmodload
2) 2 42.19 21.10 23.91% 42.19 21.10 23.91% compaudit
3) 2 59.64 29.82 33.80% 17.45 8.72 9.89% compinit
4) 1 18.06 18.06 10.24% 17.25 17.25 9.77% _zsh_highlight_load_highlighters
5) 2 13.08 6.54 7.41% 13.08 6.54 7.41% promptinit
6) 1 12.89 12.89 7.31% 12.89 12.89 7.31% is-callable
7) 1 8.69 8.69 4.92% 8.69 8.69 4.92% _zsh_highlight_bind_widgets
8) 1 6.81 6.81 3.86% 6.81 6.81 3.86% prompt_pure_state_setup
9) 2 15.57 7.79 8.82% 3.50 1.75 1.98% prompt_pure_setup
10) 1 2.91 2.91 1.65% 2.91 2.91 1.65% async_init
11) 13 2.32 0.18 1.31% 2.32 0.18 1.31% (anon)
12) 11 2.09 0.19 1.19% 2.09 0.19 1.19% add-zsh-hook
13) 2 4.40 2.20 2.50% 1.50 0.75 0.85% async
14) 3 1.32 0.44 0.75% 1.32 0.44 0.75% is-at-least
15) 3 0.54 0.18 0.31% 0.48 0.16 0.27% add-zle-hook-widget
16) 1 16.53 16.53 9.37% 0.24 0.24 0.14% set_prompt
17) 1 16.73 16.73 9.48% 0.20 0.20 0.11% prompt
18) 1 0.12 0.12 0.07% 0.12 0.12 0.07% compdef
モジュール読み込みの時間短縮を試みてみる
~/.zprezto/modules/ 以下をzcompileする
code:zsh
$ find ~/.zprezto/modules -name "*.zsh" | while read line; do echo $line; zcompile $line; done
時間を測ってみる
code:zsh
$ ./avgtime_zsh.sh
Average: .457
0.5秒を切った
もう一度 プロファイルを見てみる
code:zprof
num calls time self name
-----------------------------------------------------------------------------------
1) 2 43.59 21.80 32.84% 43.59 21.80 32.84% compaudit
2) 3 82.40 27.47 62.08% 33.60 11.20 25.31% pmodload
3) 2 56.30 28.15 42.41% 12.71 6.35 9.57% compinit
4) 1 7.93 7.93 5.97% 7.93 7.93 5.97% _zsh_highlight_bind_widgets
5) 2 7.50 3.75 5.65% 7.50 3.75 5.65% promptinit
6) 1 7.17 7.17 5.40% 6.61 6.61 4.98% _zsh_highlight_load_highlighters
7) 1 5.97 5.97 4.50% 5.97 5.97 4.50% prompt_pure_state_setup
8) 2 14.48 7.24 10.91% 3.85 1.93 2.90% prompt_pure_setup
9) 1 2.80 2.80 2.11% 2.80 2.80 2.11% async_init
10) 13 2.40 0.18 1.81% 2.40 0.18 1.81% (anon)
11) 11 1.76 0.16 1.33% 1.76 0.16 1.33% add-zsh-hook
12) 3 1.63 0.54 1.23% 1.63 0.54 1.23% is-at-least
13) 2 3.84 1.92 2.89% 1.04 0.52 0.78% async
14) 3 0.53 0.18 0.40% 0.47 0.16 0.35% add-zle-hook-widget
15) 1 15.62 15.62 11.77% 0.46 0.46 0.35% set_prompt
16) 1 15.82 15.82 11.92% 0.20 0.20 0.15% prompt
17) 1 0.17 0.17 0.13% 0.17 0.17 0.13% compdef
18) 1 0.04 0.04 0.03% 0.04 0.04 0.03% is-callable
compinitの時間を短縮する
code:.zshrc
autoload -Uz compinit
compinit
と書いていた部分をこの記事を参考に、次のように書き直した code:.zshrc
_compinit() {
local re_initialize=0
for match in ${ZDOTDIR}/.zcompdump*(.Nmh+24); do
re_initialize=1
break
done
autoload -Uz compinit
compinit
# update the timestamp on compdump file
compdump
else
# omit the check for new functions since we updated today
compinit -C
fi
}
_compinit
.zcompdumpの更新時間を見て24時間以内であればチェックを飛ばすようになっている
これで時間を測ってみると
code:zsh
$ ./avgtime_zsh
...
Average: .414
code:zprof
num calls time self name
-----------------------------------------------------------------------------------
1) 3 74.88 24.96 92.71% 23.60 7.87 29.21% pmodload
2) 2 12.11 6.05 14.99% 12.11 6.05 14.99% compinit
3) 2 6.78 3.39 8.39% 6.78 3.39 8.39% promptinit
4) 1 6.53 6.53 8.09% 6.53 6.53 8.09% _zsh_highlight_bind_widgets
5) 1 6.22 6.22 7.70% 6.22 6.22 7.70% is-callable
6) 1 6.08 6.08 7.53% 6.08 6.08 7.53% prompt_pure_state_setup
7) 1 6.83 6.83 8.46% 6.06 6.06 7.51% _zsh_highlight_load_highlighters
8) 2 14.25 7.12 17.64% 3.13 1.56 3.87% prompt_pure_setup
9) 1 2.96 2.96 3.66% 2.96 2.96 3.66% async_init
10) 13 2.14 0.16 2.65% 2.14 0.16 2.65% (anon)
11) 11 1.87 0.17 2.32% 1.87 0.17 2.32% add-zsh-hook
12) 2 4.18 2.09 5.18% 1.22 0.61 1.51% async
13) 3 0.93 0.31 1.16% 0.93 0.31 1.16% is-at-least
14) 3 0.53 0.18 0.66% 0.47 0.16 0.58% add-zle-hook-widget
15) 1 5.13 5.13 6.35% 0.21 0.21 0.26% _compinit
16) 1 14.95 14.95 18.51% 0.18 0.18 0.23% set_prompt
17) 1 15.11 15.11 18.71% 0.16 0.16 0.19% prompt
18) 1 0.12 0.12 0.15% 0.12 0.12 0.15% compdef
compinitが28.15→6.05となり、compauditの呼び出しがなくなった
pyenvの初期化を遅延呼び出しする
eval (pyenv init -)が.zshrcで呼ばれていた。
この実行時間を測ってみると
code:shell
$ time (eval "$(pyenv init -)")
( eval "$(pyenv init -)"; ) 0.16s user 0.17s system 103% cpu 0.321 total
0.3秒ほど実行に時間がかかっていた
この呼び出し部分を以下のように書き換えた
code:.zshrc
pyenv() {
unset -f pyenv
eval "$(command pyenv init -)"
pyenv $@
}
Average: .111