WSL 2 の Git を高速化する方法
Windows 上の Docker を高速化するためには WSL 2 を使うと良いというのは、以前の記事「Windows の Docker 環境を高速化する方法」で書きました。 WSL 2 にファイルを置くと Docker が早くなるのは良いのですが、それに起因して別の問題が発生します。 その WSL 2 に置いたファイルに対して Windows から Git を使用するとめちゃくちゃ遅くなります。 かなりツライのでどうにかしましょう。
遅い原因
これは結論から言うと、Windows の Docker のバインドマウントが遅くなるのと同じ原因です。
つまり、Windows のファイルシステムと、WSL 2(つまり Linux)のファイルシステムとの間での変換処理が遅いのです。 Windows から WSL 2 のファイルにアクセスしたり、 WSL 2 から Windows のファイルにアクセスしたりすると、ファイルシステムの変換処理が入ってしまい遅くなるのです。
下記の2つの例を見てください。 この2つは両方とも遅くなる例です。
- Windows にインストールした Git(git.exe)で、WSL 2 にあるファイル(\\wsl.localhost\ 配下)を処理する
- WSL 2 にインストールした Git(/usr/bin/git)で、Windows にあるファイル(/mnt/c/ 配下)を処理する
![slow.png](/img/ja/blog/230307/slow.png)
なお、これは Git だけに関する話ではないです。 例えば、Windows にインストールした PHP(php.exe) で、WSL 2 にある PHP ファイルを処理したり、 Windows にインストールした Node.js(node.exe) で、WSL 2 にある JavaScript ファイルを処理したりしても同じことが発生します。 つまり、どんなツールを使っていたとしても、ファイルシステムを跨いでしまったらそれだけで遅くなってしまうのです。
解決方法
なので解決方法としては、ファイルシステム間の変換処理を発生させないようにすれば良いのです。 つまり、実行ファイルのある場所と、処理対象のファイルの場所を合わせておけば良いのです。
- Windows にインストールした Git(git.exe)で、Windows にあるファイルを処理する
- WSL 2 にインストールした Git(/usr/bin/git)で、WSL 2 にあるファイル を処理する
![slow.png](/img/ja/blog/230307/fast.png)
そんなの当たり前、簡単じゃないかって思いますか? CUI だけを使っている場合でしたら確かにその通りです。 問題なのは、Windows にインストールした GUI のツールを使っている場合です。
WSL 2 で GUI の Git クライアントが遅い
せっかく WSL 2 を使っているのであれば、Windows にインストールした GUI のツールを使いたいところでしょう。 GUI のツールを使えるということが、WSL 2 を使用するメリットの一つです。 しかし、GUI のツールで WSL 2 のファイルにアクセスしてしまうと、 ファイルシステムの変換処理を経由してしまうため、やはりどうしても遅くなってしまいます。 ファイルシステムの変換処理からは逃れられないのです。
あまりファイルにアクセスしないようなツールであれば、少しぐらい遅くなっても問題にはなりません。 しかし、Git はそうではありません。 Git は大量のファイルアクセスが必要なツールです。 ファイルの数が多ければ多いほど遅くなってしまうのです。 GUI の Git クライアント(例えば、TortoiseGit、Sourcetree、VS Code など)を使っている場合でも同様です。
![gui.png](/img/ja/blog/230307/gui.png)
解決策1:GUI を諦める
ではどうすれば良いかという話なのですが、 GUI を諦めて CUI だけにしてしまうというのも一つの手かもしれません。 冗談のように聞こえるかもしれませんが、熟練した使い手達には GUI など必要ないのです。 WSL 2 のターミナルを開いて、そちらで全ての作業するというような形にしてしまえば速度は問題ないでしょう。
VS Code を使用しているのであれば、VS Code から WSL 2 のターミナルを開いて作業することもできます。
![vscode_cui.png](/img/ja/blog/230307/vscode_cui.png)
解決策2:VS Code の WSL 拡張機能を使用する
まぁ、さすがに GUI を諦めたくないだろうということでいろいろと調べてみましたが、 結論としては VS Code の WSL 拡張機能を使用するのが良いのではないでしょうか。
VS Code に WSL 拡張機能をインストールすると、VS Code がクライアントとサーバーの2つに分割されて、 VS Code と WSL 2 との間で通信をしてくれるようになります。 このような形にすることで、Windows 上の VS Code から、WSL 2 上の Linux の Git を使用している状態にすることができます。 ファイルシステムを跨ぐことがなくなるため、処理速度の低下を最小限に抑えることができます。
![vscode_wsl.png](/img/ja/blog/230307/vscode_wsl.png)
一見すると、解決策1の GUI を諦めてターミナル経由で使用する方法と同じように見えるかもしれませんが、そうではありません。 この方法を使用すると、VS Code 上で行う全ての作業でファイルシステムの変換処理が無くなります。 つまり、VS Code のアクティビティバー(左端の縦のバー)の「Source Control」ビューも早くなりますし、 ファイルの検索も早くなりますし、拡張機能も早くなるということです。
これはかなりスゴイ機能なのではないでしょうか? もうテキストエディタという概念の範疇を超えていると思います。 VS Code と WSL 2 を作った Microsoft だからこそできると言っても過言ではない気がします。
なお、VS Code の Git の GUI はデフォルトではかなり貧弱ですが、 VS Code の Git の拡張機能はたくさんありますので、 お好きなものをインストールして使用すると良いでしょう。 VS Code に Git の拡張機能をインストールする方法は後述します。
WSL 拡張機能のインストール
VS Code に WSL 拡張機能をインストールするには、 拡張機能の検索欄に「wsl」と入力して検索しインストールします。 おそらく一番上に出てくるので迷わないとは思いますが、 もし同じ名前の拡張機能が表示された場合は、Microsoft 社製のものかどうかを確認しましょう。
![install.png](/img/ja/blog/230307/install.png)
WSL 拡張機能を起動する
WSL 拡張機能がインストールできたら起動してみましょう。
WSL 拡張機能を使用して起動すると VS Code の新しいウィンドウとして開きます。 左下の緑のところに「WSL」と表示されているのを確認しましょう。 実はウィンドウを開いて起動するだけで、VS Code クライアントと VS Code サーバーの2つに分かれた状態に既になっています。 開いたウィンドウはその VS Code クライントの状態になっているのですが、 特に意識せずに普通の VS Code と同じように使うと良いでしょう。 VS Code のターミナルも WSL 2 のターミナルに切り替わっています。
VS Code サーバーの方は、初回起動時にディストリビューションに自動的にインストールされます。 インストールされる場所は、ディストリビューションの "~/.vscode-server" になるようです。
![new_window.png](/img/ja/blog/230307/new_window.png)
起動方法は主に下記の2つです。
ディストリビューションのターミナルから開く
WSL 2 のディストリビューションのターミナルに code .
と入力すると、
そのディレクトリをワークスペースとして VS Code が開きます。
![terminal.png](/img/ja/blog/230307/terminal.png)
なお、code
コマンドで VS Code が起動するのは、
VS Code をインストールする際に PATH を通すチェックボックスにチェックを付けてインストールしたからです。
code
コマンドで VS Code が起動しない場合は、VS Code をインストールする際に、
PATH を通すチェックボックスのチェックを外した可能性がありますので注意しましょう(デフォルトではチェックが付いてます)。
![path.png](/img/ja/blog/230307/path.png)
コマンドパレットから開く
コマンドパレットを使用するには、Ctrl + Shift + P を使用します。 コマンドパレットで「>wsl」と入力すると、WSL 拡張機能で追加されたコマンドを検索できます。 WSL 2 のデフォルトのディストリビューションで新しいウィンドウを開きたい場合は、「WSL: New WSL Window」を選択します。 使用するディストリビューションを指定したい場合は、「WSL: New WSL Window using Distro...」を選択しましょう。
![palette.png](/img/ja/blog/230307/palette.png)
Git の拡張機能をインストールする
WSL 拡張機能を使用すると Git が遅い問題は解決すると思うのですが、 今度は VS Code の Git の GUI はデフォルトではかなり貧弱で使いづらいという別の問題が発生します。 しかしながら、VS Code の Git の拡張機能はたくさんありますので、 お好きなものをインストールして使用すると良いでしょう。 拡張機能の検索欄に「git」と入力して検索するといっぱい出てくると思います。
なお、拡張機能は起動するディストリビューションごとにインストールする必要があるので注意してください。 これはおそらく、VS Code サーバーにインストールする必要があるためだと思われます。 自分がどのディストリビューションのウィンドウで作業しているか迷った場合は、 左下の緑で「WSL」と表示されているところを確認しましょう。
![extension.png](/img/ja/blog/230307/extension.png)
それでも遅い?
GUI を諦めて CUI だけで操作するようにしてみたり、VS Code の WSL 拡張機能を使用したりすることで、 ファイルシステムの変換処理は無くなっているはずです。 しかし、これでもまだ Git が遅いという場合は、さらに別の原因がある可能性があります。 むしろファイルシステムの変換処理の問題より、こちらの問題の方が速度の影響が大きいかもしれません。
.git/index ファイルの再構築合戦
Git は .git ディレクトリの配下に index というファイルを生成していて、このファイルの中にデータをキャッシュしたりしています。 厄介なことにこの index ファイルは、Windows の Git が更新したのか、WSL 2(つまり Linux) の Git が更新したのかでファイルの中身が変わってしまいます。 index ファイルを更新した方のシステムではキャッシュが効いて早くなるのですが、違う方のシステムではキャッシュが効かなくなって遅くなってしまいます。
また、git status
コマンドを実行した際に、index ファイルの再構築処理が走ってしまい、それにも時間がかかってしまいます。
Windows の Git と Linux の Git の両方を同時に使ったりしていると、お互いがそれぞれ index ファイルの再構築処理を行ってしまうという、再構築合戦が始まってしまうのです。
![index.png](/img/ja/blog/230307/index.png)
Windows の Git と Linux の Git を同時に使うからこんなことが起きるのであって、同時に使わなければこんなこと起きないのです。 どちらか片方だけで使うと決めて、そちらで index ファイルを再構築するようにしましょう。 Linux にファイルを置いてあるなら、Linux の Git を動作させるべきだと思いますので、 Linux の Git で index ファイルを再構築しておけば良いでしょう。
.git/index ファイルを再構築する
index ファイルを再構築したい場合は、再構築したい環境で git status
コマンドを実行します。
再構築する必要があれば、index ファイルが再構築されます。
再構築する必要が無いなら再構築されませんので、そのままの状態で使用すれば良いでしょう。
git status
Refresh index: 48% (954/1984)