Git を WSL と Win32 の両方で使っているとき、たまに git status
などのコマンドがめちゃくちゃ遅くなることがあります。常識的に考えて WSL と Win32 の両方で Git を使うようなことはないかと思いきや、PhpStorm や Sublime Text のプラグインとかで使われているので結構な頻度で起こります。
これは Git がインデックスとワーキングツリーとの比較で stat(3)
の多くの情報を用いてファイルの更新の有無を判断しているためです。
次のように core.checkStat
を minimal
にすれば mtime
(秒単位)とファイルサイズのみで比較されるようになるので、だいぶ改善します。
# WSL
git config --global core.checkStat minimal
# Win32
git.exe config --global core.checkStat minimal
詳細
git status
を連続して実行しているときはそれほどは遅くないですが、
# WSL
$ time git status
On branch master
nothing to commit, working tree clean
real 0m0.239s
user 0m0.016s
sys 0m0.297s
# WSL
$ time git status
On branch master
nothing to commit, working tree clean
real 0m0.243s
user 0m0.000s
sys 0m0.328s
Win32 側の git status
を実行すると・・・
# Win32
$ time git.exe status
On branch master
nothing to commit, working tree clean
real 0m0.491s
user 0m0.016s
sys 0m0.016s
その直後の WSL の git status
がめちゃめちゃ遅いです。
# WSL
$ time git status
On branch master
nothing to commit, working tree clean
real 0m0.958s
user 0m0.234s
sys 0m0.766s
その後はもとに戻ります。
# WSL
$ time git status
On branch master
nothing to commit, working tree clean
real 0m0.232s
user 0m0.000s
sys 0m0.266s
core.checkStat
を minimal
にすれば WSL と Win32 で交互に実行しても速度はあまり変わらなくなります。
# WSL
git config --global core.checkStat minimal
# Win32
git.exe config --global core.checkStat minimal
# WSL
$ time git status
On branch master
nothing to commit, working tree clean
real 0m0.259s
user 0m0.016s
sys 0m0.313s
# Win32
$ time git.exe status
On branch master
nothing to commit, working tree clean
real 0m0.146s
user 0m0.000s
sys 0m0.016s
# WSL
$ time git status
On branch master
nothing to commit, working tree clean
real 0m0.263s
user 0m0.031s
sys 0m0.313s
もっと詳細
Git のインデックスファイルにはステージしたファイルだけでなく、ワーキングツリーのファイルのメタ情報も含まれています。git status
するとワーキングツリーを走査してファイルのメタ情報をインデックスと比較し、ファイルが更新されていればファイルを読んでハッシュを再計算してインデックスを更新したうえでその情報を用いて git status
の結果が表示されます。
インデックスには stat 構造体の多くが記録されており、デフォルトではこれらの多くの情報を用いてワーキングツリーとインデックスが比較されるのですが、WSL と Win32 では一致することが決して無いので(dev とか ino とか uid とか gid とか)、WSL と Win32 で交互に実行すると常にすべてのファイルが更新されたものとしてファイルの読み込みが発生します。
core.checkStat
を minimal
にすると、ワーキングツリーとインデックスの比較が mtime(秒単位)とファイルサイズでのみ比較されるようになるため、WSL と Win32 で交互に git status
しても問題ありません。