Docker Desktop for mac 4.6 がリリースされて、ファイルIOのパフォーマンスが向上したらしいので調べてみた。(virtiofs)

# Docker Desktop for mac 4.6のアップデート内容

https://www.docker.com/blog/speed-boost-achievement-unlocked-on-docker-desktop-4-6-for-mac

今回のアップデートでは、 **`virtiofs`** と呼ばれるファイル共有実装を使用するオプションを利用できるようになったみたいです。
これにより macOS ホストと DockerVM 間でファイルを同期する方法が改善され、パフォーマンスが向上したらしい。

### 「virtiofs」を使用する際の前提条件
- macOS 12.2以降 （Apple Siliconの場合）
- macOS 12.3以降 （Intelの場合）

# 「virtiofs」を有効にする

### 

- まずは Docker Desktop for mac を v4.6 にアップグレードする。（[こちら](https://docs.docker.com/desktop/mac/release-notes)からもアップグレード可能です）
- 「設定」（歯車のアイコン）>「Experimental Features」に移動し、「Use the new Virtualization framework」 と「Enable VirtiofS accelerated directory sharing」にチェックを入れる。
- 次に「Apply & Restart」をクリックして、Docker Desktopをリスタートする。

![スクリーンショット 2022-03-23 10.24.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249777/979257ed-6635-8f2b-8f9b-0d2ad4c61a27.png)

これで準備は完了です。
あとはdocker環境を起動すれば、`virtiofs`が適応されているはずです。

# 実際にファイル同期のパフォーマンスを比較してみる
### テストの内容
今回はPHPのフレームワーク`Laravel`のプロジェクトを作成し、`docker-compose`で適当に立てたコンテナの`/var/test/`に配置。
コンテナ内の`/var/test/`から100MBのファイルを作成して、ホスト側と同期されるまでのスピードを計測していきます。

### ベンチマーク用の環境準備
- まずは適当なディレクトリで`Laravel`の適当なプロジェクトを作成する。
```shell
$ curl -s "https://laravel.build/test-app" | bash
```

- 次に`docker-compose.yml`をプロジェクト内に作成する。
※すでにLaravel sail環境の`docker-compose.yml`が用意されているが、今回はあくまで簡易的なテストなので下記の構成に書き換えています。

```docker-compose.yml
version: "2"

services:
  web:
    image: httpd
    container_name: test-web
    volumes:
      - .:/var/test
    ports:
      - 8090:8090
```

- Docker環境の起動
```shell
$ docker-compose up　-d
```

### 「virtiofs」 の有無でのパフォーマンスの比較結果

#### まず、`virtiofs`**無効**の場合の結果

```shell
# コンテナの中に入る
$ docker exec -it test-web bash
```

```
~# cd /var/test

/var/test# time dd if=/dev/zero of=speedtest bs=1024 count=102400
102400+0 records in
102400+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 34.4202 s, 3.0 MB/s

real    0m34.428s ←　結果
user    0m0.186s
sys     0m1.280s

/var/test# ls -lh speedtest
-rw-r--r-- 1 root root 100M Mar 24 01:32 speedtest

```

100MBファイルの作成に**約34秒**もかかっており、かなりパフォーマンスが悪いことがわかりますね。。


#### 次に、`virtiofs`を**有効**にした場合の結果
```
~# cd /var/test

/var/test# time dd if=/dev/zero of=speedtest bs=1024 count=102400
102400+0 records in
102400+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 8.23497 s, 12.7 MB/s

real    0m8.238s ←　結果
user    0m0.217s
sys     0m3.550s

/var/test# ls -lh speedtest
-rw-r--r-- 1 root root 100M Mar 24 01:39 speedtest
```
`virtiofs`を有効にすると、なんと**約8秒**という結果が出ております!
約4~5倍の高速化が実現されていますね。

他にも、macOSユーザーコミュニティでファイルシステム操作の完了にかかる時間が最大９８％短縮された例もあるみたいです。

https://github.com/docker/roadmap/issues/7#issuecomment-1044452206


# 「mutagen」 ｖｓ 「virtiofs」
せっかくなので、先日記事を上げた`mutagen-compose`とのファイル同期のパフォーマンスの比較もしてみました。

https://qiita.com/JO95/items/15d01956ebf0b83fbdc4

まずは`docker-compose.yml`の設定。


```docker-compose.yml
version: "2"

services:
  web:
    image: httpd
    container_name: test-web
    volumes:
      - mutagen-volume:/var/test
    ports:
      - 8090:8090

volumes:
  mutagen-volume:

x-mutagen:
  sync:
    mutagen-volume:
      mode: "two-way-resolved" # 同期モード指定（ホスト　↔　コンテナ　双方を同期）
      alpha: "." # プロジェクトのパス
      beta: "volume://mutagen-volume" # volumeの指定

```
- Docker + mutagen環境の起動
```shell
$ mutagen-compose up　-d
```

```shell
# コンテナの中に入る
$ docker exec -it test-web bash
```

### **Docker Desktop for mac + mutagenの結果**


```
~# cd /var/test

/var/test# time dd if=/dev/zero of=speedtest bs=1024 count=102400
102400+0 records in
102400+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.301483 s, 348 MB/s

real    0m0.304s ←　結果
user    0m0.055s
sys     0m0.247s

/var/test# ls -lh speedtest
-rw-r--r-- 1 root root 100M Mar 24 01:44 speedtest

```

結果は、**約0.3秒**でした。
うん、ダントツで速いですね笑
勝敗は比べるまでもなく`mutagen`のほうが早かったです。

# まとめ
確かに、今回の Docker Desktop for mac 4.6のアップデートで追加された`virtiofs`で、今までかなり遅かったファイル同期が改善された。
ローカル環境にブラウザからアクセスした際のページ読み込みのパフォーマンスもなかなか早くなっていて、使っていてもストレスはないと思った。
ただ、サードパーティーのファイル同期システム`mutagen`を使ったほうが断然早かったという結果になりました。

ちなみに、volume引数のオプションに`delegated`を設定すれば` Docker Desktop for mac + virtiofs `だけでも十分速いかも。
これはまた今度試してみようと思います。