Aqutras Members' Blog

株式会社アキュトラスのメンバーが、技術情報などを楽しく書いています。

もっさりした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

github.com

です.