もっさりしたzshを改善する方法
こんにちは。maxmellon です。
この記事では、普段活用しているshell、その中でも zsh の設定ファイルである .zshrc を
整理するためのtipsを紹介したいと思います。
この記事を書いたきっかけは、社内チャットで fish の 話題が上がったからです。
「そういえば、なんとなーくターミナルがもっさりしてるなー...改善できないかなー?」 「そういえば、シェルの設定ファイル汚いなー」
と思っているそこのあなた! そんな貴方様への記事だと思います。
目次
本題に入る前に .zshrc と .zshenv の違いを理解する
PATHを重複しないようにする
.zshrc を compile する
zsh が おそい理由を分析する
実際にやってみた結果
本題に入る前に .zshrc と .zshenv の違いを理解する
実は,.zshrc と .zshenv 以外にも .zprofile, .zlogin があります.
それぞれ,実行するタイミングによって、読み込まれたり読み込まれなかったり、順番が異なったりします。
自分は,基本的には,.zshrc と .zshenv に設定を書いて運用しています.
具体的な読み込み順は
http://qiita.com/muran001/items/7b104d33f5ea3f75353f
を参照するとわかりやすいです。

ログアウトの時だけ,localが読まれてからglobal が読まれるので注意しておきましょう
PATHを重複しないようにする
tmux やらインタラクティブに zsh を走らせたりしたらPATHが増えていませんか?
PATHが重複して増えると、コマンドの探索に時間がかかり、各コマンドの応答が もっさりしてきます。
次のようなアプローチをとれば、PATHが重複するのを防げます。
$TMUXの存在を確認して、条件わけする。.zshenvを一度読み込んだあとは、読み込まないように工夫する。
好みや、メリットを考えたうえで、どちらか選択で良いと思います。
$TMUX の存在を確認して、条件わけする。
tmux を起動すると、環境変数を引き継いでいるにも関わらず、PATHが重複してしまします。

($HOME/local/bin が重複している)
それを防ぐために、 $TMUX が存在した時は、$PATH を付け加えないようにします。
~/.zshenv
before
export PATH="${HOME}/local/bin:${PATH}"
after
if [ -z $TMUX ]; then export PATH="${HOME}/local/bin:${PATH}" fi
.zshenv を一度読み込んだあとは、読み込まないように工夫する。
私は、.zshenv を一度読み込んで更新の必要のないものは、再度読み込まないように
しています。
~/.zshenv
before
export PATH="${HOME}/local/bin:${PATH}"
after
if [ -z $ZSH_ENV_LOADED ]; then export PATH="${HOME}/local/bin:${PATH}" export $ZSH_ENV_LOADED="1" else print ".zshenv の 読み込みをスキップしました \n" fi
.zshrc を compile する
私は、つい最近しったのですが、 .zshrc は コンパイルすることができます。
zcompile で .zshrc をコンパイルすることができ、.zshrc.zwc が生成されます
.zshrc.zwc がホームディレクトリに存在するとき、 .zshrc は読み込まれず、
.zshrc.zwc だけが読み込まれます。
分割せずに長くなった、.zshrc に特に有効です。
自分は、プラグインマネージャーを用いて、各コマンドを読み込んでいて、
実質分割しているのと同等なのであまり飛躍的な効果は得られませんでした。
計測コマンド
$ time ( zsh -i -c exit )
コンパイル前

コンパイル後

起動が早すぎて誤差なのか改善したのかわかりませんでした。
もう少し大規模な .zshrc になれば、優位な差が出ると思います。
.zshrc更新したら自動でコンパイルする
大規模なzshを、compileするのは良いのですが、毎回コンパイルするのは大変面倒です。
そこで、.zshrc と .zshrc.zwc 比較して .zshrc のほうが新しければ、
コンパイルするという設定を記述しておきましょう。
参考記事 : http://blog.n-z.jp/blog/2013-12-10-auto-zshrc-recompile.html
~/.zshrc
if [ ~/.zshrc -nt ~/.zshrc.zwc ]; then zcompile ~/.zshrc fi
.zshrc.zwc が存在しないと、.zshrc のコンパイルが行われないので、
.zshrc 設置時に zcompile を実行するか、デプロイスクリプトで、
自動でコンパイルして設置するようにしておきましょう。
zsh が おそい理由を分析する
zmodule である zprof を用いて、どの処理が時間をかかっているのかを分析する。
zprof を用いるには、 zmodload コマンドで読み込む必要があるので
.zshenv に追記をする。
今回は、起動時の状態を調査したいので、 zprof の実行を .zshrc に追記します。
.zshenv 行頭 に次の処理を追記
zmodload zsh/zprof && zprof
.zshrc 行末 に次の処理を追記
if (which zprof > /dev/null) ;then zprof | less fi
するとこんな感じの画面が表示されます。

これを見れば呼ばれた回数と、時間などがわかると思います。
左から順番に
id, 呼び出し回数, 全回数の処理時間(ms), 1回あたりの処理時間(ms)...
%は全部足しても100にならないので、ちょっと何かわからないです。
自分の場合、nvm の初期化と保管系、ハイライト系がほとんどでした。
anyenv 系のイニシャルコストを最小限に抑える
rbenv init - には rehash が含まれていて遅い。
シェル起動毎に、rbenv rehash する必要がなければ、
rbenv init - --no-rehash とすればよい。
こうすると、tmux のペインを切る動作が明らかに早くなる。
上記にかかれていることを全部やってみて比較
before

after

わかりにくいかもしれませんが、かなり高速になっています。
最終的に、

から

へ
tmuxの起動やペインの作成でストレスがたまる生活とはさようならです.
私の .dotfiles は
です.