Docker for Macの新しいファイルシステムVirtioFSを試してみた
この記事はUMITRON Advent Calendar 2021 2日目の記事です。
背景
Docker for Macのファイルアクセスは遅く、本家のGitHubにもissueがあり長年議論が重ねられてきています。
これらの経緯は以前Qiitaにまとめたので興味があれば参照ください。
Docker for Macチームも改善を重ねてきていますが、現在デフォルトのファイルシステムのgRPC-FUSEでもまだユーザの満足を得られる速さとは言えません。
最近この問題を改善したVirtioFSというファイルシステムを実装したDocker for Macの実験ビルドが公開されました。以下のリンク先からダウンロードし、指示通り設定すれば試すことが出来ます。
このVirtioFSでファイルシステムパフォーマンスがどれほど改善されたかベンチマークを取ってみました。
ベンチマーク手法
弊社では一部でDocker+Railsを使っていて、今のDocker for Macそのままではテスト実行が遅く開発がスピーディに行えないと感じることがあります。このテストの速さが改善されるか直接試したかったのですが、現状公開されてるビルドではVirtioFSはまだ完全ではなく、弊社のRailsのテストは動きませんでした。
Railsのテストが遅いのは多くのファイルを読み込む必要があるのが大きな要因だと考えられるので、多くのファイルを読み込む時間を測ることにします。具体的には5KBのファイルを2万個用意し、ひたすらこれを順々に読み込む時間を測ります。テストに使ったコードはここで確認できます。
Intel MacとM1 Macどちらも試します。また、ついでに一時期Docker for MacのEdgeリリースにも入っていたmutagen.ioも試します。
ベンチマーク結果
Machine | File System | Time(seconds) |
---|---|---|
M1 | gRPC-FUSE | 17.934 |
M1 | VirtioFS | 5.239 |
M1 | mutagen(gRPC-FUSE) | 0.4772 |
Intel | gRPC-FUSE | 24.974 |
Intel | VirtioFS | 37.843 |
Intel | mutagen(gRPC-FUSE) | 0.7402 |
まとめ
M1 MacではVirtioFSがgRPC-FUSEの3.4倍速く、Intel Macでは逆に1.5倍遅い結果になりました。また、それでもmutagenと比べると全然遅いことも合わせてわかりました。
Dockerの中の人によるとIntelチップでは新しいvirtualization frameworkにスピードの問題が確認されているとのことなので、それが関係していると思われます。
これはあくまで簡単なベンチマークですしまだ開発中のものなので、安定版がリリースされ実際のワークロードで実行した場合にどれほど変わるのか分かりません。ですが、もし実際にM1 Macで数倍速くなるのであれば使える日が楽しみです。
補遺
ベンチマークログ
M1, gRPC-FUSE
$ docker compose run --rm bench hyperfine --warmup 2 './justread.sh files'
Benchmark 1: ./justread.sh files
Time (mean ± σ): 17.934 s ± 1.493 s [User: 0.618 s, System: 2.744 s]
Range (min … max): 16.703 s … 21.484 s 10 runs
M1, virtiofs
$ docker compose run --rm bench hyperfine --warmup 2 './justread.sh files'
Benchmark 1: ./justread.sh files
Time (mean ± σ): 5.239 s ± 0.115 s [User: 0.671 s, System: 1.745 s]
Range (min … max): 5.101 s … 5.517 s 10 runs
Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet PC without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.
M1, mutagen(gRPC-FUSE)
$ docker compose run --rm bench hyperfine --warmup 2 './justread.sh files'
Benchmark 1: ./justread.sh files
Time (mean ± σ): 477.2 ms ± 4.9 ms [User: 248.1 ms, System: 310.5 ms]
Range (min … max): 468.0 ms … 483.4 ms 10 runs
Intel, gRPC-FUSE
$ docker compose run --rm bench hyperfine --warmup 2 './justread.sh files'
Benchmark 1: ./justread.sh files
Time (mean ± σ): 24.974 s ± 1.081 s [User: 1.089 s, System: 2.359 s]
Range (min … max): 23.706 s … 27.347 s 10 runs
Intel, virtiofs
$ docker compose run --rm bench hyperfine --warmup 2 './justread.sh files'
Benchmark 1: ./justread.sh files
Time (mean ± σ): 37.843 s ± 6.001 s [User: 6.608 s, System: 14.749 s]
Range (min … max): 33.198 s … 54.131 s 10 runs
Intel, mutagen(grpc-fuse)
$ docker compose run --rm bench hyperfine --warmup 2 './justread.sh files'
Benchmark 1: ./justread.sh files
Time (mean ± σ): 740.2 ms ± 45.4 ms [User: 457.4 ms, System: 362.8 ms]
Range (min … max): 700.1 ms … 834.8 ms 10 runs
書き込み速度
単純な1ファイル書き込みに関しては、特にM1においてかなり速いようです。M1ではVirtioFSがgRPC-FUSE17倍、Intelでは2.9倍速い結果になりました。
Machine | File System | Time(seconds) |
---|---|---|
M1 | VirtioFS | 3.371 |
M1 | gRPC-FUSE | 58.657 |
Intel | VirtioFS | 18.581 |
Intel | gRPC-FUSE | 54.549 |
書き込みベンチマークログ
M1, VirtioFS
$ docker compose run --rm bench hyperfine --warmup 1 'dd if=/dev/zero of=speedtest bs=1024 count=100000'
Benchmark 1: dd if=/dev/zero of=speedtest bs=1024 count=100000
Time (mean ± σ): 3.371 s ± 0.392 s [User: 0.161 s, System: 1.254 s]
Range (min … max): 2.784 s … 3.962 s 10 runs
M1, gRPC-FUSE
$ docker compose run --rm bench hyperfine --warmup 1 'dd if=/dev/zero of=speedtest bs=1024 count=100000'
Benchmark 1: dd if=/dev/zero of=speedtest bs=1024 count=100000
Time (mean ± σ): 58.657 s ± 2.796 s [User: 0.258 s, System: 4.499 s]
Range (min … max): 55.249 s … 64.318 s 10 runs
Intel, VirtioFS
$ docker compose run --rm bench hyperfine --warmup 1 'dd if=/dev/zero of=speedtest bs=1024 count=100000'
Benchmark 1: dd if=/dev/zero of=speedtest bs=1024 count=100000
Time (mean ± σ): 18.581 s ± 0.968 s [User: 2.302 s, System: 9.771 s]
Range (min … max): 17.017 s … 19.893 s 10 runs
Intel, gRPC-FUSE
$ docker compose run --rm bench hyperfine --warmup 1 'dd if=/dev/zero of=speedtest bs=1024 count=100000'
Benchmark 1: dd if=/dev/zero of=speedtest bs=1024 count=100000
Time (mean ± σ): 54.549 s ± 1.123 s [User: 0.325 s, System: 4.679 s]
Range (min … max): 53.137 s … 56.360 s 10 runs
参考
テスト環境
M1 Mac: MacBook Pro(16-inch, 2021), Apple M1 Pro, メモリ32GB, macOS 12.0.1
Intel Mac: MacBook Pro(15-inch, 2017), 2.9 GHz クアッドコアIntel Core i7, メモリ16GB, macOS 12.0.1
Docker for Macの設定(共通): CPUs 4, Memory 6GB, Swap 1.5GB
Discussion