(追記: 2021-07-18) 本記事の続編 => zshの起動がいつの間にか速くなっていた - valid,invalid
zshの起動速度が遅いのをずっと放置していたので改善した。もともと遅かったので自慢できる数字ではないが、とても大雑把に言うと起動時間がおよそ3秒→1秒と3倍速くなった。
やったこと
zprofでボトルネック特定
今回はこの方法を知ることが出来たので一番の収穫だったかもしれない。
まず、単純にtime
コマンドで計測するとおおまかな処理時間はわかるが、ボトルネックがわからない。
# チューニング前の time コマンド実行結果 ❯ for i in $(seq 1 10); do time zsh -i -c exit; done zsh -i -c exit 1.84s user 1.29s system 103% cpu 3.013 total zsh -i -c exit 1.90s user 1.32s system 103% cpu 3.119 total zsh -i -c exit 1.96s user 1.37s system 103% cpu 3.199 total zsh -i -c exit 1.92s user 1.30s system 104% cpu 3.092 total zsh -i -c exit 2.04s user 1.49s system 102% cpu 3.445 total zsh -i -c exit 1.90s user 1.34s system 103% cpu 3.140 total zsh -i -c exit 1.90s user 1.29s system 103% cpu 3.073 total zsh -i -c exit 2.23s user 1.53s system 91% cpu 4.109 total zsh -i -c exit 2.35s user 1.91s system 84% cpu 5.025 total zsh -i -c exit 2.01s user 1.53s system 101% cpu 3.493 total
「zsh 起動 遅い」等でググるとzprof
なるものが提供されているとわかった。zshの起動が遅いのでなんとかしたい - Qiita に従って.zshenv
の最初と.zshrc
の最後に以下を付け足す。
# .zshenv zmodload zsh/zprof && zprof
# .zshrc if (which zprof > /dev/null 2>&1) ;then zprof fi
すると起動時にプロファイル結果が出力される。長いので詳細は省略している。
num calls time self name ----------------------------------------------------------------------------------- 1) 6 2320.87 386.81 68.33% 907.63 151.27 26.72% pmodload 2) 2 888.63 444.32 26.16% 888.32 444.16 26.16% nvm_die_on_prefix 3) 2 1916.71 958.35 56.44% 449.40 224.70 13.23% nvm_auto 4) 1 372.65 372.65 10.97% 372.25 372.25 10.96% __kubectl_bash_source 5) 4 1467.30 366.83 43.20% 356.07 89.02 10.48% nvm 6) 2 222.32 111.16 6.55% 198.99 99.50 5.86% nvm_ensure_version_installed 7) 1 74.28 74.28 2.19% 73.80 73.80 2.17% _zsh_highlight_load_highlighters 8) 2 29.95 14.97 0.88% 29.95 14.97 0.88% compaudit 9) 1 25.38 25.38 0.75% 25.38 25.38 0.75% -zcache-hook-antigen 10) 2 23.32 11.66 0.69% 23.32 11.66 0.69% nvm_is_version_installed 11) 2 16.74 8.37 0.49% 16.74 8.37 0.49% nvm_supports_source_options 12) 2 41.45 20.73 1.22% 11.51 5.75 0.34% compinit 13) 21 10.90 0.52 0.32% 10.90 0.52 0.32% (anon) 14) 2 9.60 4.80 0.28% 9.60 4.80 0.28% promptinit 15) 1 6.95 6.95 0.20% 6.95 6.95 0.20% _zsh_highlight_bind_widgets 16) 1 4.06 4.06 0.12% 4.06 4.06 0.12% async_init 17) 2 8.09 4.05 0.24% 2.22 1.11 0.07% prompt_pure_setup 18) 12 1.79 0.15 0.05% 1.79 0.15 0.05% add-zsh-hook 19) 2 5.55 2.77 0.16% 1.48 0.74 0.04% async 20) 1 1.47 1.47 0.04% 1.47 1.47 0.04% colors 21) 3 0.87 0.29 0.03% 0.87 0.29 0.03% is-at-least 22) 1 0.78 0.78 0.02% 0.78 0.78 0.02% -antigen-interactive-mode 23) 4 0.65 0.16 0.02% 0.65 0.16 0.02% compdef 24) 4 0.59 0.15 0.02% 0.59 0.15 0.02% nvm_has 25) 2 1933.81 966.91 56.94% 0.36 0.18 0.01% nvm_process_parameters 26) 1 8.84 8.84 0.26% 0.20 0.20 0.01% set_prompt 27) 4 0.19 0.05 0.01% 0.19 0.05 0.01% -set-default 28) 1 5.57 5.57 0.16% 0.16 0.16 0.00% -antigen-env-setup 29) 1 0.40 0.40 0.01% 0.15 0.15 0.00% complete 30) 1 0.18 0.18 0.01% 0.12 0.12 0.00% -zcache-antigen 31) 1 25.48 25.48 0.75% 0.10 0.10 0.00% zcache-start 32) 2 0.23 0.12 0.01% 0.09 0.05 0.00% -zcache-antigen-hook 33) 1 8.90 8.90 0.26% 0.06 0.06 0.00% prompt 34) 1 0.04 0.04 0.00% 0.04 0.04 0.00% bashcompinit 35) 1 0.04 0.04 0.00% 0.04 0.04 0.00% is-callable 36) 2 0.03 0.02 0.00% 0.03 0.02 0.00% nvm_is_zsh 37) 1 0.26 0.26 0.01% 0.03 0.03 0.00% antigen 38) 1 0.06 0.06 0.00% 0.02 0.02 0.00% antigen-bundle
nvm
関連とpmodload
関連の処理が重いとわかった。
nvm.sh を遅延ロードしてシェルの起動を高速化
NVM の nvm.sh を遅延ロードしてシェルの起動を高速化する - Qiita
↑の記事の対応をそのまま行ったところ、0.5~0.8秒ほどの改善が見られた。
❯ for i in $(seq 1 10); do time zsh -i -c exit; donezsh -i -c exit 1.46s user 1.01s system 99% cpu 2.480 total zsh -i -c exit 1.42s user 0.95s system 100% cpu 2.364 total zsh -i -c exit 1.42s user 0.96s system 100% cpu 2.372 total zsh -i -c exit 1.43s user 0.97s system 98% cpu 2.431 total zsh -i -c exit 1.44s user 0.97s system 95% cpu 2.539 total zsh -i -c exit 1.46s user 0.98s system 100% cpu 2.429 total zsh -i -c exit 1.38s user 0.97s system 103% cpu 2.278 total zsh -i -c exit 1.38s user 0.95s system 103% cpu 2.242 total zsh -i -c exit 1.40s user 0.93s system 104% cpu 2.223 total zsh -i -c exit 1.41s user 0.91s system 104% cpu 2.219 total
num calls time self name ----------------------------------------------------------------------------------- 1) 6 1738.74 289.79 81.14% 610.52 101.75 28.49% pmodload 2) 1 984.57 984.57 45.95% 401.19 401.19 18.72% nvm_auto 3) 1 362.83 362.83 16.93% 362.45 362.45 16.91% __kubectl_bash_source 4) 1 302.44 302.44 14.11% 302.29 302.29 14.11% nvm_die_on_prefix 5) 2 583.38 291.69 27.23% 170.47 85.23 7.96% nvm 6) 1 110.33 110.33 5.15% 97.92 97.92 4.57% nvm_ensure_version_installed 7) 1 69.76 69.76 3.26% 69.33 69.33 3.24% _zsh_highlight_load_highlighters 8) 1 29.12 29.12 1.36% 29.12 29.12 1.36% -zcache-hook-antigen 9) 2 28.16 14.08 1.31% 28.16 14.08 1.31% compaudit 10) 1 12.41 12.41 0.58% 12.41 12.41 0.58% nvm_is_version_installed 11) 2 40.29 20.14 1.88% 12.13 6.06 0.57% compinit 12) 21 10.97 0.52 0.51% 10.97 0.52 0.51% (anon) 13) 2 9.25 4.62 0.43% 9.25 4.62 0.43% promptinit 14) 1 8.08 8.08 0.38% 8.08 8.08 0.38% nvm_supports_source_options 15) 1 6.63 6.63 0.31% 6.63 6.63 0.31% _zsh_highlight_bind_widgets 16) 1 3.20 3.20 0.15% 3.20 3.20 0.15% async_init 17) 12 1.81 0.15 0.08% 1.81 0.15 0.08% add-zsh-hook 18) 1 1.21 1.21 0.06% 1.21 1.21 0.06% colors 19) 2 5.35 2.68 0.25% 1.02 0.51 0.05% prompt_pure_setup 20) 3 0.81 0.27 0.04% 0.81 0.27 0.04% is-at-least 21) 4 0.71 0.18 0.03% 0.71 0.18 0.03% compdef 22) 2 3.90 1.95 0.18% 0.71 0.35 0.03% async 23) 1 0.34 0.34 0.02% 0.34 0.34 0.02% -antigen-interactive-mode 24) 2 0.30 0.15 0.01% 0.30 0.15 0.01% nvm_has 25) 1 992.92 992.92 46.34% 0.27 0.27 0.01% nvm_process_parameters 26) 4 0.21 0.05 0.01% 0.21 0.05 0.01% -set-default 27) 1 6.11 6.11 0.29% 0.21 0.21 0.01% set_prompt 28) 2 0.38 0.19 0.02% 0.18 0.09 0.01% -zcache-antigen-hook 29) 1 6.42 6.42 0.30% 0.18 0.18 0.01% -antigen-env-setup 30) 1 0.26 0.26 0.01% 0.16 0.16 0.01% -zcache-antigen 31) 1 29.28 29.28 1.37% 0.16 0.16 0.01% zcache-start 32) 1 0.38 0.38 0.02% 0.14 0.14 0.01% complete 33) 1 0.43 0.43 0.02% 0.06 0.06 0.00% antigen 34) 1 0.05 0.05 0.00% 0.05 0.05 0.00% is-callable 35) 1 6.16 6.16 0.29% 0.05 0.05 0.00% prompt 36) 1 0.04 0.04 0.00% 0.04 0.04 0.00% bashcompinit 37) 1 0.09 0.09 0.00% 0.03 0.03 0.00% antigen-bundle 38) 1 0.01 0.01 0.00% 0.01 0.01 0.00% nvm_is_zsh
しかし見てみると、nvm
関連の処理がまだまだ存在している… 奴はすでに葬ったはずでは…?
ここまでの変更は Lazy load nvm · ohbarye/dotfiles@5b0653b · GitHub である。
preztoのmodule読み込みで対象を減らした
プロファイラの結果をよくみると、nvm_auto
やnvm_die_on_prefix
といった処理はpmodload
から呼ばれているとわかった。
pmodload
が何をしているかというと、.zpreztorc
の定義にしたがってpreztoのmoduleをloadする。名前そのままだ。
# .zpreztorc zstyle ':prezto:load' pmodule \ 'environment' \ ... # つづく
ここでloadしているmoduleにnode
があったのでこれを消すと途端に速度が上がった。
この他にも使わないmoduleがないかを確認していき、ひとつずつ消していった結果のcommit: Do not load unused modules given by prezto · ohbarye/dotfiles@70fa79e · GitHub
各moduleが何をしているのかパッと見てはわからないので、https://github.com/sorin-ionescu/prezto/tree/master/modulesから一つずつ確認した。中には読んでもわからないものがあったので、一度そのmoduleを消してzshを再起動して普段と変わりなく操作できるかを確認したりもした。
大概はまったく使っていないaliasが使えなくなる程度なので大して困らなさそうだという気持ちでゴリゴリ消していった。一つmoduleを減らすたびにだいたい100~200 msec ほど高速化していったのでこれはやりがいがあった。
最終的な結果は以下:
❯ for i in $(seq 1 10); do time zsh -i -c exit; done zsh -i -c exit 0.79s user 0.40s system 108% cpu 1.100 total zsh -i -c exit 0.78s user 0.39s system 108% cpu 1.070 total zsh -i -c exit 0.77s user 0.39s system 108% cpu 1.069 total zsh -i -c exit 0.79s user 0.39s system 109% cpu 1.083 total zsh -i -c exit 0.78s user 0.38s system 108% cpu 1.065 total zsh -i -c exit 0.80s user 0.40s system 108% cpu 1.099 total zsh -i -c exit 0.79s user 0.40s system 109% cpu 1.090 total zsh -i -c exit 0.80s user 0.40s system 107% cpu 1.110 total zsh -i -c exit 0.79s user 0.40s system 108% cpu 1.100 total zsh -i -c exit 0.80s user 0.40s system 108% cpu 1.100 total
num calls time self name ----------------------------------------------------------------------------------- 1) 1 363.84 363.84 54.43% 363.55 363.55 54.39% __kubectl_bash_source 2) 4 266.00 66.50 39.80% 135.32 33.83 20.24% pmodload 3) 1 73.05 73.05 10.93% 72.62 72.62 10.86% _zsh_highlight_load_highlighters 4) 2 27.63 13.82 4.13% 27.63 13.82 4.13% compaudit 5) 1 27.16 27.16 4.06% 27.16 27.16 4.06% -zcache-hook-antigen 6) 2 37.80 18.90 5.66% 10.17 5.08 1.52% compinit 7) 2 7.16 3.58 1.07% 7.16 3.58 1.07% promptinit 8) 1 7.06 7.06 1.06% 7.06 7.06 1.06% _zsh_highlight_bind_widgets 9) 14 6.48 0.46 0.97% 6.48 0.46 0.97% (anon) 10) 1 3.63 3.63 0.54% 3.63 3.63 0.54% async_init 11) 12 1.84 0.15 0.27% 1.84 0.15 0.27% add-zsh-hook 12) 1 1.20 1.20 0.18% 1.20 1.20 0.18% colors 13) 2 5.90 2.95 0.88% 1.06 0.53 0.16% prompt_pure_setup 14) 3 0.90 0.30 0.13% 0.90 0.30 0.13% is-at-least 15) 2 4.44 2.22 0.66% 0.81 0.40 0.12% async 16) 1 0.30 0.30 0.05% 0.30 0.30 0.05% -antigen-interactive-mode 17) 2 0.26 0.13 0.04% 0.26 0.13 0.04% compdef 18) 1 6.68 6.68 1.00% 0.21 0.21 0.03% set_prompt 19) 4 0.21 0.05 0.03% 0.21 0.05 0.03% -set-default 20) 1 5.59 5.59 0.84% 0.19 0.19 0.03% -antigen-env-setup 21) 1 0.29 0.29 0.04% 0.16 0.16 0.02% complete 22) 1 0.20 0.20 0.03% 0.14 0.14 0.02% -zcache-antigen 23) 2 0.25 0.13 0.04% 0.10 0.05 0.01% -zcache-antigen-hook 24) 1 27.25 27.25 4.08% 0.09 0.09 0.01% zcache-start 25) 1 6.73 6.73 1.01% 0.05 0.05 0.01% prompt 26) 1 0.04 0.04 0.01% 0.04 0.04 0.01% is-callable 27) 1 0.04 0.04 0.01% 0.04 0.04 0.01% bashcompinit 28) 1 0.28 0.28 0.04% 0.03 0.03 0.00% antigen 29) 1 0.06 0.06 0.01% 0.02 0.02 0.00% antigen-bundle
次のボトルネックは__kubectl_bash_source
...なのだが、これはkubectl
の補完を効かせるやつ (ここ)。最近はkubectl
を触る機会があるのでこれを外すとそこそこ困るうえに代替案がパッと思いつかなかったので一旦放置。外すとようやく1秒未満で起動するようになるので補完機能も遅延で追加できたりしないかな。