zshの起動が遅いのでなんとかしたい 2

関連記事
- [zshの起動が遅いのでなんとかしたい](https://qiita.com/vintersnow/items/7343b9bf60ea468a4180)
- [最速のZsh プラグインマネージャーを求めて](https://qiita.com/vintersnow/items/cef72aebb2d55a82f212)

# TL;DR

zplugを使うのやめた。

zcompile最強

# はじめに

男たるもの常に最速を目指さないといけないと思っているvinterです。
嘘です。ちょっと卒論がやばいので現実逃...ではなく息抜きにzshの起動速度のチューンをしていました。
なので正確なデータを取り忘れました。すみません。

以前[zshの起動が遅いのでなんとかしたい](http://qiita.com/vintersnow/items/7343b9bf60ea468a4180)という記事を書いたのでよければそちらもどうぞ。

初っ端からちょっとアレでしたが、別にzplugをディスているわけではないです。zplugはとても素晴らしいプラグインマネージャーです。
プロファイル取る時分かりにくかったのと、もともとそんなにプラグイン使っていなかったので使うのやめた感じです。

# 現状

zshの起動速度を見るために以下のコマンドで計測しています。

```zsh
time ( zsh -i -c exit )
```

これで大体200msぐらいでした。そのうち、自分で書いた設定ファイルが50ms、zplug関連が150msでした。なのでこれ以上の高速化をするならzplugとプラグインをどうにかしないといけないなとなりました。

# 原因究明
まずzplugが遅いのか、そもそもプラグインが重いのかを計るために0プラグインでzplugをloadしてみました。
それでも50~100msくらいかかってました。
zprofで見てみるとzplugの`__load__`が結構時間かかっていますね。特にcompinitが-iなのでこれが全体の50%ほど時間を占めているようです。

# zplug脱却

`compinit -i`を`compinit -C`にするとセキュリティチェックをすべて全て飛ばすので数倍早くなります。
ただ残念ながらzplug内でcompinitをしているので、外部からいじれません。
なのでzplugをやめで手動でロードするようにしました。
つまり今は`zplugでプラグインインストールやアップデート→ロードは手動`というちょっとひどい構成になっています。
zplugがcompinitのオプションを外部から変更出来るようになったら戻ってくると思います。

そもそも常に-Cというのも流石に不安なので定期的にcompinitをするべきでしょう。[こういう感じ](https://gist.github.com/ctechols/ca1035271ad134841284)にすれば、一応定期的にcompinit出来ますがあんまりキレイな書き方ではないですね。
一時の快楽（高速化）のために不便を強いているような...

compinitの速度についていっぺん調べてみたいのですが、何がどう影響しているのか知識がなくて諦めました。

ともあれこれで80msほど短縮。

# プラグインの調整

`compinit`が一番重い処理でしたが、そもそもプラグイン自体も結構ロードに時間がかかっています。
自分の場合[zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting)が30ms、[enhancd](https://github.com/b4b4r07/enhancd)が20msかかっていました。

このうち、enhacdはlogファイルを保存しておくためのmkdirとtouchを毎回していたので、すでに存在したら飛ばすようにしたら10ms縮まりました。

```diff
--- a/init.sh
+++ b/init.sh
@@ -43,8 +43,12 @@ __enhancd::init::init()
     unset src

     # make a log file and a root directory
-    mkdir -p "$ENHANCD_DIR"
-    touch "$ENHANCD_DIR/enhancd.log"
+    if [ ! -d "$ENHANCD_DIR" ]; then
+      mkdir -p "$ENHANCD_DIR"
+    fi
+    if [ ! -f "$ENHANCD_DIR/enhancd.log" ]; then
+      touch "$ENHANCD_DIR/enhancd.log"
+    fi
```

あとは`src`以下のファイルをzcompileしたところ6msぐらいなりました。最初の4倍ですね！
ところでこのenhancdってautoloadじゃ駄目だったんかな？重いよね。

zsh-syntax-highlightingは`_zsh_highlight_load_highlighters`という関数が30msほどかかっていました。
これは大量のファイルをsourceしているところなので`highlighters`ディレクトリ以下のzshファイルを全部zcompileしちゃいます。

```zsh
for f in $(find . -name "*.zsh"); do zcompile $f; done
```

なんと3msになりました！１０倍です！１０倍！

# 結果

```zsh
~
❯ type zshtime
zshtime is an alias for for i in $(seq 1 10); do time zsh -i -c exit; done
~
❯ zshtime
zsh -i -c exit  0.05s user 0.05s system 87% cpu 0.122 total
zsh -i -c exit  0.04s user 0.04s system 100% cpu 0.077 total
zsh -i -c exit  0.04s user 0.04s system 101% cpu 0.076 total
zsh -i -c exit  0.04s user 0.04s system 100% cpu 0.076 total
zsh -i -c exit  0.04s user 0.04s system 101% cpu 0.081 total
zsh -i -c exit  0.04s user 0.04s system 101% cpu 0.079 total
zsh -i -c exit  0.04s user 0.04s system 101% cpu 0.077 total
zsh -i -c exit  0.04s user 0.04s system 101% cpu 0.077 total
zsh -i -c exit  0.04s user 0.04s system 101% cpu 0.079 total
zsh -i -c exit  0.04s user 0.04s system 100% cpu 0.077 total
```

ついに100ms切りました。やったね。

# デメリット

今回の高速化で以下の点を気にする必要が出来ました。

+ zcompdumpが壊れていないのか。
+ zcompdumpのzcompileを行う。
+ プラグインを更新したとき、zcompileを手動でする。

# 結論

zcompile最強。
ロードする時自動でzcompileする用に設定とか出来ないんですかね？

# Appendix

基本的にzprofで見ているのですが、もう少し詳しくみたい時があります。そのとき以下のようにすると行ごとにtimestampがとれて便利です。

```zsh
zmodload zsh/datetime
setopt promptsubst
PS4='+$EPOCHREALTIME %N:%i> '
exec 3>&2 2>/tmp/zsh_profile.$$
setopt xtrace prompt_subst

# 計測したい処理

trap 'unsetopt xtrace' EXIT
exec 2>&3 3>&-
```

```zsh:zsh_profile.444444
+1481803140.2755711079 _zsh_highlight_load_highlighters:8> setopt localoptions noksharrays
+1481803140.2756168842 _zsh_highlight_load_highlighters:11> [[ -d /Users/vinter/.zplug/repos/zsh-users/zsh-syntax-highlighting/highlighters ]]
+1481803140.2756500244 _zsh_highlight_load_highlighters:17> local highlighter highlighter_dir
+1481803140.2757830620 _zsh_highlight_load_highlighters:18> highlighter_dir=/Users/vinter/.zplug/repos/zsh-users/zsh-syntax-highlighting/highlighters/brackets/
+1481803140.2757980824 _zsh_highlight_load_highlighters:19> highlighter=brackets 
+1481803140.2758131027 _zsh_highlight_load_highlighters:20> [[ -f /Users/vinter/.zplug/repos/zsh-users/zsh-syntax-highlighting/highlighters/brackets/brackets-highlighter.zsh ]]
...
```