Macのターミナルを高速化する
Macのターミナルの動作が遅いのが気になったので、改善を試みました。
前提
Macのzsh環境を前提としています。
やったこと
今回実施したのは以下の内容です。
.zshrcから不要な設定を削除
jenvの無効化
oh-my-zshの無効化
gitの情報取得&表示(vcs_info)の最適化
vcs_infoの実行タイミングを以下に限定する
ディレクトリ移動時
gitコマンド実行時
.zshrcから不要な設定を削除
まずは起動時に時間がかかっている処理をzprofで確認しました。
.zshrcの先頭と最後に以下を設定するとスタッツが表示されます。
# 先頭行
zmodload zsh/zprof && zprof
:
:
# 最終行
if (which zprof > /dev/null) ;then
zprof | cat
fi
改善前の状況
Last login: Sun Jun 9 18:51:18 on ttys027
num calls time self name
-----------------------------------------------------------------------------------
num calls time self name
-----------------------------------------------------------------------------------
1) 1 628.35 628.35 47.62% 628.35 628.35 47.62% _jenv_export_hook
2) 22 336.87 15.31 25.53% 254.52 11.57 19.29% _omz_source
3) 4 161.91 40.48 12.27% 161.91 40.48 12.27% compaudit
4) 2 222.91 111.45 16.89% 61.00 30.50 4.62% compinit
5) 1 52.36 52.36 3.97% 52.36 52.36 3.97% zrecompile
6) 1 47.14 47.14 3.57% 47.14 47.14 3.57% test-ls-args
7) 1 40.35 40.35 3.06% 40.35 40.35 3.06% (anon)
8) 1 65.24 65.24 4.94% 24.90 24.90 1.89% handle_update
9) 7 22.30 3.19 1.69% 22.30 3.19 1.69% add-zsh-hook
10) 3 11.05 3.68 0.84% 11.05 3.68 0.84% bashcompinit
11) 1 5.56 5.56 0.42% 5.56 5.56 0.42% regexp-replace
12) 16 4.59 0.29 0.35% 4.59 0.29 0.35% compdef
13) 5 2.40 0.48 0.18% 2.40 0.48 0.18% is-at-least
14) 1 1.89 1.89 0.14% 1.89 1.89 0.14% colors
15) 4 1.77 0.44 0.13% 0.72 0.18 0.05% complete
16) 3 0.20 0.07 0.02% 0.20 0.07 0.02% is_theme
17) 2 0.12 0.06 0.01% 0.12 0.06 0.01% is_plugin
18) 1 0.10 0.10 0.01% 0.10 0.10 0.01% install_hook
19) 2 0.08 0.04 0.01% 0.08 0.04 0.01% env_default
-----------------------------------------------------------------------------------
jenv, oh-my-zsh, compinitなどに時間がかかっていることがわかります。
このうちjenvとoh-my-zshを無効化しました。
jenvはそもそもJavaのバージョン切り替えを頻繁に行うことがないので不要。oh-my-zshはプロンプトの見栄えのカスタマイズだけにしか使っていなかったので、テーマファイルを直接.zshrcから読み込むように変更しました。
gitの情報取得&表示(vcs_info)の最適化
vcs_infoが、起動時だけでなくコマンド実行のたびに呼ばれることが動作のもっさり感の原因となっていました。
ブランチ状態の可視化とパフォーマンスのトレードオフとなるため、今回は妥協点としてvcs_infoの実行タイミングを以下に限定することにしました。
ディレクトリ移動時
gitコマンド実行時
(シェル起動時やコマンド実行のたびに実行するのをやめる)
vcs_infoの設定例は以下のとおりです。
oh-my-zshのsteeefテーマの設定をベースに一部修正しました。このファイルを.zshrc内で直接読み込めばOKです。
# 参考: https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/steeef.zsh-theme
export VIRTUAL_ENV_DISABLE_PROMPT=1
function virtualenv_info {
[ $VIRTUAL_ENV ] && echo '('%F{blue}`basename $VIRTUAL_ENV`%f') '
}
setopt prompt_subst
autoload -U add-zsh-hook
autoload -Uz vcs_info
#use extended color palette if available
if [[ $terminfo[colors] -ge 256 ]]; then
turquoise="%F{81}"
orange="%F{214}"
purple="%F{135}"
hotpink="%F{163}"
limegreen="%F{002}"
else
turquoise="%F{cyan}"
orange="%F{yellow}"
purple="%F{magenta}"
hotpink="%F{red}"
limegreen="%F{green}"
fi
# gitのみ有効化
zstyle ':vcs_info:*' enable git
# check-for-changes can be really slow.
# you should disable it, if you work with large repositories
zstyle ':vcs_info:*:prompt:*' check-for-changes true
# set formats
# %b - branchname
# %u - unstagedstr (see below)
# %c - stagedstr (see below)
# %a - action (e.g. rebase-i)
# %R - repository path
# %S - path in the repository
PR_RST="%f"
FMT_BRANCH_BASE="[%b]%u%c"
FMT_BRANCH=${FMT_BRANCH_BASE}
FMT_ACTION="(%{$limegreen%}%a${PR_RST})"
FMT_UNSTAGED="%{$orange%}+${PR_RST}"
FMT_STAGED="%{$limegreen%}!${PR_RST}"
zstyle ':vcs_info:*:prompt:*' unstagedstr "${FMT_UNSTAGED}"
zstyle ':vcs_info:*:prompt:*' stagedstr "${FMT_STAGED}"
zstyle ':vcs_info:*:prompt:*' actionformats "${FMT_BRANCH}${FMT_ACTION}"
zstyle ':vcs_info:*:prompt:*' formats "${FMT_BRANCH}"
zstyle ':vcs_info:*:prompt:*' nvcsformats ""
# gitコマンド実行時に呼ばれる
function steeef_preexec {
case "$2" in
*git*)
PR_GIT_UPDATE=1
;;
esac
}
add-zsh-hook preexec steeef_preexec
# ディレクトリ変更時に呼ばれる
function steeef_chpwd {
PR_GIT_UPDATE=1
}
add-zsh-hook chpwd steeef_chpwd
# コマンド実行毎に呼ばれる
function steeef_precmd {
if [[ -n "$PR_GIT_UPDATE" ]] ; then
# untrackedファイルをチェックする(vcs_infoでは取得できないため)
if git ls-files --other --exclude-standard 2> /dev/null | grep -q "."; then
FMT_BRANCH="${FMT_BRANCH_BASE}%{$purple%}*${PR_RST}"
else
FMT_BRANCH="${FMT_BRANCH_BASE}"
fi
zstyle ':vcs_info:*:prompt:*' formats "${FMT_BRANCH}"
vcs_info 'prompt'
PR_GIT_UPDATE=
fi
}
add-zsh-hook precmd steeef_precmd
PROMPT=$'
%F{8}%n@%m %*${PR_RST}
[%{$limegreen%}%~${PR_RST}]$vcs_info_msg_0_$(virtualenv_info)
$ '
改善結果
上記の改善結果がこちらです。約1605ms(改善前) → 約151ms(改善後)と大幅に高速化しました。
シェル起動時だけでなく、毎回のコマンド実行時のもたつきが解消され、Enterキーを連打しても待たされず快適になりました。
Last login: Sun Jun 9 19:54:20 on ttys026
num calls time self name
-----------------------------------------------------------------------------------
num calls time self name
-----------------------------------------------------------------------------------
1) 1 99.62 99.62 95.35% 53.55 53.55 51.25% compinit
2) 2 46.07 23.04 44.10% 46.07 23.04 44.10% compaudit
3) 2 1.86 0.93 1.78% 1.86 0.93 1.78% bashcompinit
4) 3 1.67 0.56 1.60% 1.67 0.56 1.60% add-zsh-hook
5) 4 0.75 0.19 0.72% 0.75 0.19 0.72% compdef
6) 4 1.33 0.33 1.27% 0.57 0.14 0.55% complete
Header photo by Unsplash Chris Liverani