【zsh高速化】え～、そんなプラグインマネージャーがあるんだったらもっと早く教えてよ、と姉が怒り出した - Zinit (旧名Zplugin)

# TL;DR
- zplugから~~Zplugin~~**Zinit**へ

# 2020.03.06追記
2020.01.19に、ZpluginはZinitという名称へ変更されたようです。
名称変更に伴い、本記事の内容もZinit用に変更しました。


> * 19-01-2020
  - The name has been changed to **Zinit** based on the results of the poll.  

 （[zdharma/zinit](https://github.com/zdharma/zinit)より）

とはいえ、元々のZpluginユーザーがするべきことは特にありません。
もしZinitに移行するなら、行うべき変更は2つだけです。

- Zinitをインストールする
- .zshrc内の`zplugin`を`zinit`に変更する



# はじめに
zshの起動高速化を試みました。
zplugから~~Zplugin~~Zinitに乗り換えただけで、起動時間を**約1.5秒**から**約0.4秒**まで短縮できました。
なお、起動時間は以下のコマンドで計測しました。参考値程度に考えてください。

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

# まずは現状
もとのzshの起動時間は**約1.5秒**でした。（設定ファイルはzcompile済み）

```
( zsh -i -c exit; )  1.04s user 0.40s system 94% cpu 1.519 total
( zsh -i -c exit; )  1.00s user 0.39s system 94% cpu 1.462 total
( zsh -i -c exit; )  1.02s user 0.40s system 94% cpu 1.502 total
```

使用しているプラグインは以下の3つです。言わずと知れた[zplug](https://github.com/zplug/zplug)のお世話になっております。

- [momo-lab/zsh-abbrev-alias](https://github.com/momo-lab/zsh-abbrev-alias)：略語を展開してくれる
- [zsh-users/zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting)：実行可能なコマンドに色付け
- [zsh-users/zsh-completions](https://github.com/zsh-users/zsh-completions)：コマンド補完


ちなみに、まっさらな状態のzshの起動は爆速です。

```
( zsh -i -c exit; )  0.00s user 0.00s system 79% cpu 0.011 total
```

# 遅い原因を探る
まず、`.zshenv`の先頭に以下を追記します。

```shell:.zshenv
zmodload zsh/zprof && zprof
```

次に、`.zshrc`の最後尾に以下を追記。

```shell:.zshrc
if (which zprof > /dev/null) ;then
  zprof | less
fi
```

結果は以下のようになりました。ボトルネックになっているのはプラグイン関連ぽい（適当）。

```
num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    1         254.77   254.77   44.29%    253.25   253.25   44.02%  __zplug::log::write::info
 2)    5          90.50    18.10   15.73%     90.50    18.10   15.73%  __zplug::io::print::f
 3)    2          31.36    15.68    5.45%     31.36    15.68    5.45%  compaudit
 4)    2          61.74    30.87   10.73%     30.39    15.19    5.28%  compinit

...
```



<!---
# zcompile
zshのdotfilesはコンパイルすることができます。やり方は非常に簡単で、例えば`.zshrc`をコンパイルするのであれば以下の通り。

```shell
$ zcompile .zshrc
```

コンパイルすると、`.zshrc.zwc`が生成されます。

zshファイルを更新するたびに自動でコンパイルする設定にすると便利です。筆者は`.zshrc`に以下の関数を加えました。

```shell:.zshrc
# zshファイル更新したら自動でコンパイル
function() {for arg; do
  if [ ! -f "$HOME"/${arg}.zwc -o "$HOME"/${arg} -nt ${arg}.zwc ]; then
    zcompile "$HOME"/${arg}
  fi
done} .zshenv .zshrc
```

`.zsh*.zwc`がまだ生成されていない、または、`.zsh*`が`.zsh*.zwc`より新しい場合に自動コンパイルしてくれます。

`.zshenv`、`.zshrc`をコンパイルして起動時間を計測したところ、秒になりました。--->

# ~~Zplugin~~Zinit

![](https://raw.githubusercontent.com/zdharma/zinit/master/doc/img/zplugin.png)

- ~~[zdharma/zplugin](https://github.com/zdharma/zplugin)~~
- [zdharma/zinit](https://github.com/zdharma/zinit)

~~**Zplugin**~~**Zinit**というプラグインマネージャーが速いらしいので試してみることに。（[dotfilesをキレイキレイするついでに晒す - Qiita](https://qiita.com/sei40kr/items/2a49fde94b8ed5c1a9d4)）
インストールは簡単で、以下を実行するだけです（不安な方は[公式のREADME](https://github.com/zdharma/zplugin#installation)へ）。`~/.zinit/bin`にZinitがインストールされます。

```shell
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zinit/master/doc/install.sh)"
```



次に、~~Zplugin~~Zinit用に`.zshrc`を書き換えます。

```diff:.zshrc
-source ~/.zplug/init.zsh
-zplug 'momo-lab/zsh-abbrev-alias' # 略語を展開する
-zplug 'zsh-users/zsh-syntax-highlighting' # 実行可能なコマンドに色付け
-zplug 'zsh-users/zsh-completions' # 補完
-# Install check
-if ! zplug check --verbose; then
-  printf 'Install? [y/N]: '
-  if read -q; then
-    echo; zplug install
-  fi
-fi
-zplug load --verbose

+### Added by Zplugin's installer
+source "${HOME}/.zinit/bin/zinit.zsh"
+autoload -Uz _zinit
+(( ${+_comps} )) && _comps[zinit]=_zinit
+zinit load momo-lab/zsh-abbrev-alias # 略語を展開する
+zinit load zsh-users/zsh-syntax-highlighting # 実行可能なコマンドに色付け
+zinit load zsh-users/zsh-completions # 補完
```

結果、起動時間が**約0.4秒**になりました。これならほとんど起動時間が気になりません。~~Zplugin~~Zinit恐るべし。

```
( zsh -i -c exit; )  0.26s user 0.13s system 93% cpu 0.414 total
( zsh -i -c exit; )  0.26s user 0.13s system 93% cpu 0.417 total
( zsh -i -c exit; )  0.24s user 0.12s system 94% cpu 0.379 total
```

# ~~Zplugin~~Zinitでさらなる高速化
## 遅延読み込み
`ice wait`を使うことでプラグインを遅延読み込みできます。
これが非常に強力で、例えば以下のように`ice wait'0'`とすると、zshが起動した後に**0秒**置いてhoge/hogeプラグインを読み込むことになります。

```shell:.zshrc
zinit ice wait'0'; zinit load hoge/hoge # プラグイン読み込み
```

起動時に必要なプラグインでなければ、遅延読み込みしてもさしたる問題はないでしょう。すなわち、この**0秒**遅延読み込みにより起動がさらに高速化されます。

筆者は2つのプラグインを遅延読み込みしています。

```diff:.zshrc
zinit load momo-lab/zsh-abbrev-alias # 略語を展開する
- zinit load zsh-users/zsh-syntax-highlighting # 実行可能なコマンドに色付け
- zinit load zsh-users/zsh-completions # 補完

zinit load momo-lab/zsh-abbrev-alias # 略語を展開する
+ zinit ice wait'!0'; zinit load zsh-users/zsh-syntax-highlighting # 実行可能なコマンドに色付け
+ zinit ice wait'!0'; zinit load zsh-users/zsh-completions # 補完
```

（`wait'0'`ではなく`wait'!0'`とすると、読み込み完了のメッセージが出なくなる）

遅延読み込み後の起動時間は**約0.3秒**となりました！~~Zplugin~~Zinit恐るべし。

```
( zsh -i -c exit; )  0.15s user 0.08s system 93% cpu 0.240 total
( zsh -i -c exit; )  0.16s user 0.08s system 91% cpu 0.264 total
( zsh -i -c exit; )  0.17s user 0.09s system 87% cpu 0.293 total
```

<!--
## zcompile
公式のREADMEに、zcompileを勧める記述がありました。

> It's good to compile zplugin into Zsh bytecode:
>
>```
> zcompile ~/.zplugin/bin/zplugin.zsh
>```
>

試してみましたが、筆者の環境では効果を実感できず。無念。-->

# まとめ
~~Zplugin~~Zinitの導入により、zshの起動時間を**約1.5秒→約0.4秒→約0.3秒**まで短縮できました。
もし~~Zplugin~~Zinitより速いプラグインマネージャーをご存知ならぜひ教えてください。


# 余談：タイトルについて
このキャッチーなタイトルは[コピーメカ](http://www.copymecha.com/)で自動生成しました。


# 参考
- [zshの起動が遅いのでなんとかしたい - Qiita](https://qiita.com/vintersnow/items/7343b9bf60ea468a4180#_reference-6c8b652a2671d4e5fd73)
- [zshの起動が遅いのでなんとかしたい 2 - Qiita](https://qiita.com/vintersnow/items/c29086790222608b28cf)
- [zshの起動が遅いと感じたら、zprofでプロファイリングしてみる - Qiita](https://qiita.com/scalper/items/86da115e6c76a692d687)
- [dotfilesをキレイキレイするついでに晒す - Qiita](https://qiita.com/sei40kr/items/2a49fde94b8ed5c1a9d4)