Windows10 Insider 18917 で WSL2 が来たので雑にボリュームマウントのベンチマークとってみた（追記あり)

# WSL2 とは

2019年5月に開催された Build 2019 で発表されたもので、今までの Windows Subsystem for Linux(WSL) のアーキテクチャから大きく変えたものとして発表されたものになります。

今までの WSL では Linux カーネルは動いておらず Linux のシステムコールを変換して動いていましたが、WSL2 では Hyper-V 上で Linux の軽量VM を動作させるという形に変わりました。

遠くから目を細めて眺めると、Docker Desktop(以前はDocker for Windowsと呼ばれていたもの)と同じように見える感じになったので、じゃあどれくらい違うのかといったことを雑にボリュームマウント周りのベンチマークとってみることにしました。

ちなみに、Docker Desktop は今の所、Windows 10 の Pro エディションでしか動かないんですが、WSL2 は Home エディションでも Hyper-V のサブセット上で動くよというアナウンスがあったので、Home エディションだから docker を動作させるために toolbox を使わないといけないみたいな人に朗報になるのでは！と期待されているものになります。

### ※追記

最初書いたときはおそすぎる！みたいな感じで書きましたが、WSL2からWindowsファイルシステムをみるのではなく、WindowsからWSL2のファイルシステムを見るほうがあってる感じっぽかったので、最後にそれを追記してます。

# ベンチマーク環境

ベンチマークを取った環境はあまり理想的な環境ではないといえばないので、そのあたりはあしからず。

- Macbook Pro Retina 13-inch Early 2015 の BootCamp 上で動作させている Windows 10 Pro
  - メモリ 16GB
  - Windows 10 Pro Insider Preview
  - バージョン 1903
  - OSビルド 18917.1000

以前、Docker Desktop を試すために、Pro にあげてしまったので、Home だったらどうなのかみたいなチェックはできないのでそれは他の方にまかせる。

Docker Desktop は以下のバージョンまで上げています。

- Version 2.0.5.0(35318)
- Channel edge

# WSL2 の状態

WSL2 のセットアップの仕方とかはもう Qiita にもちらほらあるっぽいのでそこはざっくり割愛

とりあえずこんな状態になっているという前提です。

```
> wsl -l -v
 NAME      STATE           VERSION
* Ubuntu    Running         2
```

そして動いている Ubuntu はこんな感じ

```
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.2 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
```

# mount の状態

mount コマンドを実行するとこんな感じです。

- `/` 以下は ext4 でマウントされている
- WSL のときと違ってちゃんとした？ cgroup が動いている(Linuxカーネルが動いてるんだからまぁそうだわな)
- Windowsの領域は `/mnt/c` にマウントされていて(これはWSL同様)、9p という方式でマウントされている

この 9p というマウント方式でどれくらいスピードがでるのかというのが今回のベンチマークの興味の部分となります。

```
$ mount
/dev/sda on / type ext4 (rw,relatime,discard,errors=remount-ro,data=ordered)
none on /init type 9p (ro,relatime,dirsync,aname=tools;fmask=022,loose,access=client,trans=fd,rfd=5,wfd=5)
none on /dev type devtmpfs (rw,nosuid,relatime,size=7631524k,nr_inodes=1907881,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,noatime,gid=5,mode=620,ptmxmode=000)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,noatime)
cgroup on /sys/fs/cgroup type tmpfs (rw,relatime,mode=755)
proc on /proc type proc (rw,nosuid,nodev,noexec,noatime)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
none on /run type tmpfs (rw,nosuid,noexec,noatime,mode=755)
none on /run/lock type tmpfs (rw,nosuid,nodev,noexec,noatime)
none on /run/shm type tmpfs (rw,nosuid,nodev,noatime)
none on /run/user type tmpfs (rw,nosuid,nodev,noexec,noatime,mode=755)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu type cgroup (rw,relatime,cpu)
cgroup on /sys/fs/cgroup/cpuacct type cgroup (rw,relatime,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,relatime,freezer)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,relatime,net_cls)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,relatime,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,relatime,hugetlb)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,relatime,pids)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,relatime,rdma)
C:\ on /mnt/c type 9p (rw,noatime,sync,dirsync,aname=drvfs;path=C:\;uid=0;gid=0,access=client,trans=fd,rfd=9,wfd=9)
```

# dd コマンドの実行スピード

なんか、毎年同じようなベンチマークをしているのでは？ということに気がついたんですが、2017以降、Docker for Mac/Win のボリュームマウントのベンチマークをとっていて、最初に書いた記事が以下のものになります。

- [MacおよびWinにおけるDocker環境のベンチマーク結果まとめ(2017-10-23現在)](https://qiita.com/kunit/items/0c1d4badacbb5414c178)

この中で、Docker for Mac が致命的に遅いことを示すパターンとして以下のコマンドを実行して試していました。

```
time dd if=/dev/zero of=test bs=1k count=100000
```

### 実行結果

|環境 | real | user | sys |
|:--------------------|:-----|:-----|:----|
|WSL2(ext4領域)          | 0m0.260s | 0m0.030s | 0m0.229s |
|WSL2(9pマウント)         | 0m23.560s | 0m0.798s | 0m3.474s |
|Docker Desktop(軽量VM領域) | 0m0.263s | 0m0.020s | 0m3.474s |
|Docker Desktop(Win領域)     | 0m1.181s | 0m0.020s | 0m0.250s |

結果を見てみると、

- WSL2 の Windows ファイルシステムをマウントしている 9p という方式はかなり遅い。
    - Docker for Mac の通常マウントとほぼ同じような時間がかかっているのでなにも工夫しないとこうなるってことなのか？
    - ただし、Docker for Mac はその後、read/write それぞれでキャッシュする回避策的なものがでたが、WSL2 の 9p はそういう手出しはいまのところできない(Docker for Mac のこの回避策は納得行ってないので、9p は対策するならもっとちゃんとしてほしいが...)
- Docker Desktop の Windows ファイルシステムのマウントは cifs というので行われているが、こう見るとかなり優秀なことがわかる
    - とはいえ、オーダーが一つ上がってるが...

上記のように今の所、WSL2 の 9p はかなり厳しい感じがする。

# git clone の速度

WSL2 が Build 2019 でアナウンスされたときに git clone が早くなったぜー！って言っていたので、じゃあやってみるかということでやってみた。

こちらは以下のコマンドでテストしました。（まぁ、なぜ Laravel なのかはスルーしてください)

```
time git clone git@github.com:laravel/laravel.git
```

### 実行結果

|環境 | real | user | sys |
|:--------------------|:-----|:-----|:----|
|WSL2(ext4領域)          | 0m9.818s | 0m1.215s | 0m0.468s |
|WSL2(9pマウント)         | 0m31.838s | 0m2.791s | 0m2.791s |
|Docker Desktop(軽量VM領域) | 0m9.530s | 0m1.120s | 0m0.720s |
|Docker Desktop(Win領域)     |  0m26.744s | 0m1.570s | 0m3.230s |

結果を見てみると、

- dd の結果ほどは開きはなくなったが、3倍強遅い
- git clone の結果であれば、WSL2 の 9p マウントと Docker Desktop の cifs マウントは大差ない

# まとめ

まだ、WSL2 は Insider Preview として使えるようになったばかりで、通常配布されるのは来年 2020 年の前半っぽいので、まだ1年くらいは改善されていくということを希望に待ち続けるという感じかなと。

通常のコマンド実行等はストレスなくできるので、ちょっとした作業とかでは現時点でもいいと思うんだが、使い慣れたIDEやエディタで Windows ファイルシステム側を編集しつつ、WSL2 上の Web サーバー上で実行みたいなのはちょっと現時点では辛いかもなあと。（※追記：この点に関して追記を参照)

逆に言うと、WSL2 上の vim/emacs で編集するという形であればストレスはだいぶなくなる気がするので、今だとそれがおすすめなのかな？

あと WSL2 には直接関係ないが、6月に配布される的なことをが書かれていた Windows Terminal もまだでてないので、そこもちょっと作業がやりづらい感じ。

WSL2 でボリュームマウント周りが改善されて、Windows Terminal が出たら Win10 で開発してもいいかなぁと思っていたので、本当に WSL2 に頑張ってほしい。

あれ？もしかして、VSCode Remote Development で、WSL2 上との Remote 編集をしろってことなのか？

Build 2019 のセッションをみるとそうなのかもしれない。

https://www.youtube.com/watch?v=lwhMThePdIo&t=2636

# 追記

こちらの記事では、`/mnt/c` 経由はむしろ WSL1 よりも遅くなっているということが書かれていた。

- [WSL2を使ってみる (InsiderPreview)](https://qiita.com/namoshika/items/53a9ac2df7eace656870)

WSL2の用途としては、WSL2 から Windows ファイルシステムをみるというよりも、より高速となった WSL2 上のファイルシステムを活用するために、Windows から WSL2 のファイルシステムを見に行くという形のほうが良さそう。

Ubuntu パッケージであれば以下のように WSL2 側が見れたので、Windows上のIDEやエディタでここを編集していくということで良さそうかも。

```
\\wsl$\Ubuntu
```

# 更に追記

`\\wsl$\Ubuntu` というパスだと、PhpStorm(というかおそらく JetBrains 系のIDE全てだと思う)で、プロジェクトを作成するときのパスに `$` を含んではいけないという警告が出てしまった。

それを回避するために、適当なネットワークドライブ(D:とかX:とかそれは任意)にマウントしておいて、そのドライブをつかうとすれば、PhpStormでもプロジェクトが作れたことを追記しときます。