仮想マシンにおけるファイルシステム性能の比較
原文は Mitchell Hashimoto により に公開されました。 このブログを購読する
長年、Vagrantを使った仮想マシンベースの開発環境における最大のボトルネックは、ファイルシステムの性能だった。CPUによる違いはわずかでほとんど気にならず、RAMが問題になるのは多数の仮想マシンを同時に稼働させた場合に限られる。
昨日はほぼ一日を費やして、代表的なファイルシステムの仕組みについてベンチマークと分析を行った。その結果をここで共有したい。
まずは結果の分析から始めたい。ほとんどの人にとって、そこが一番興味深い部分だろうからだ。テストの詳しい手法や使用したソフトウェア、生の結果データは、この分析のあとに掲載している。
以下に示すすべてのグラフでは、何らかの方法でファイルの読み書きをテストしている。各グラフで扱うファイルの合計サイズは固定だ。Y軸はスループット(KB/s)、X軸は「レコードサイズ」、つまり一度に読み書きするデータのチャンクのサイズ(KB)を示している。
テスト環境は、native、VirtualBox native、VMware native、VirtualBox共有フォルダ(vboxsf)、VMware共有フォルダ(vmhgfs)、そしてNFSの6種類だ。「native」環境とは、その環境でファイルシステムを単独で使った場合を指す。「native」はホストマシン上、「VirtualBox native」はVirtualBox仮想マシン内のルートデバイス上、といった具合だ。NFSはVirtualBoxでのみテストした。VirtualBoxでもVMwareでも性能特性はほぼ同じになるはずだからだ。
どのグラフでも、スループット(Y軸)は高いほど良い。
小さなファイルのシーケンシャルリード
最初は64KBのファイルを、さまざまなリード時のレコードサイズでシーケンシャルに読み込むテストだ。小さなシーケンシャルリードが現実の世界で使われる例としては、アプリケーションのソースファイルを実行やコンパイル、テストのために読み込む場合が挙げられる。

まず目を引くのは、NFSの小さなレコードサイズにおけるリード性能が驚異的だという点だ。NFSはこの性能を出すために、大規模な先読みやキャッシュを行っているのだろう。なぜNFSが仮想マシンのネイティブなファイルシステムを上回るのか、うまい説明が思いつかない。
ここではVMwareの共有フォルダがVirtualBoxの共有フォルダを圧倒している。VirtualBoxの共有フォルダのリード性能はひどいの一言だ。生データを見れば、VirtualBoxのスループットは一度も100 MB/sを超えないのに対し、VMwareは500 MB/sを下回ることがなく、ピークは900 MB/sを超えていることがわかる。
興味深いことに、仮想マシン内のネイティブなファイルシステムが、ホストマシン上のネイティブなファイルシステムを上回る場合がある。このテストではユーザースペースでのバッファリングを一切行わない生のreadシステムコールを使っている。ハイパーバイザーが仮想マシンからのリードに対してバッファリングを行っている可能性が非常に高く、ネイティブカーネルへのコンテキストスイッチが少なくなることで性能が向上しているのだろう。この仮説は、freadのベンチマークの生データを見るとさらに裏付けられる。そちらのテストでは、ネイティブなファイルシステムが毎回仮想ファイルシステムを上回っている。
大きなファイルのランダムリード
次は64MBのファイルのさまざまな箇所をランダムに読み込むスループットのテストで、こちらもさまざまなリード時のレコードサイズで検証した。このファイルは前回のテストの1000倍の大きさだ。このような挙動は、ファイルシステムにアクセスするデータベースの読み込みなどで見られるだろう。

小さなシーケンシャルリードと比べて、VMwareの共有フォルダとVirtualBoxの共有フォルダの差はさらに大きく広がっている。VirtualBoxは性能が低すぎてグラフ上でもほとんど見えない。ここでもVirtualBoxのスループットは100 MB/sを超えることがない。一方のVMwareはピークで7 GB/sに達している。さまざまなテストケースを通じてVirtualBoxのスループットのばらつきが非常に小さいことから、VirtualBoxの共有フォルダシステム内に、この性能を制限している単一のホットパスが存在するのではないかと推測している。明らかに何かが間違っている。
NFSはそれほど圧倒的ではないが、それはこのテストケースでは先読みの恩恵が得られないためだろう。それでも、他の選択肢と比べればNFSは非常に良好な性能を示している。
そして、小さなシーケンシャルリードのときと同様、仮想マシン内部の方が外部よりも良い性能が出ている。ここでも、ハイパーバイザーが巧妙なバッファリングを行っているのに対し、ホストマシンへの生のシステムコールではそれができないことが原因と考えられる。
小さなファイルのシーケンシャルライト
次に、小さなファイルへのシーケンシャルライトの性能を見てみよう。これはセッション状態の保存や一時ファイルの作成、新しいソースファイルの書き込みなどに最も近い状況だ。

最初に目につくのは、この種のライトにおけるNFSの性能がひどく悪いという点だ。ここではNFSが有効にキャッシュできる余地がほとんどなく、ネットワークのオーバーヘッド、ホスト側でのディスクへの書き込み、そしてVM側でライト成功のackを待つというフルペナルティを支払わなければならない。なんとも痛い。
さまざまな「native」ファイルシステムは非常に良好な性能を示している。ここでも仮想マシンの方がホストを上回っているが、これもハイパーバイザー側のバッファリングによるものと考えられる。
共有ファイルシステム同士は僅差だが、このテストケースではVirtualBoxがVMwareを明確に上回っている。
大きなファイルのランダムライト
最後に見るのは、大きなファイル(64MB)へのランダムライトをテストした結果だ。大規模なランダムリードのテストと同様、これはデータベースの性能を測るのに適したテストだ。

小さなシーケンシャルライトと比べて、大きな違いはあまりない。ファイルが大きいためテスト環境間のギャップは広がっているが、それ以外は結果はほぼ同じだ。
NFSはライトでは引き続きひどい性能だ。VirtualBoxの共有フォルダはライトではVMwareを上回り続けており、ハイパーバイザーはホストマシンを上回っている。
ハイパーバイザーがホストマシンを上回る点が、私にとって最も興味深い。このテスト結果は、ハイパーバイザーが性能のために同期ライトについて嘘をついていることを明確に示している。これはPackerでも見てきたことと一致する。仮想マシンが正常にシャットダウンされなかった場合、コミットされたはずのライトが失われるのだ。仮想マシン内でのfsync()は、データがホスト側に書き込まれたことを意味するのではなく、ハイパーバイザー内でコミットされたことを意味するに過ぎない。
総合的な分析
共有ファイルシステムに関して言えば、VMwareの方が求められる挙動を示している。ウェブページの読み込みやテストスイートの実行、ソフトウェアのコンパイルは、いずれもリードが非常に多い処理だ。VMwareの共有フォルダのリード性能はVirtualBoxを圧倒する一方で、VirtualBoxの共有フォルダのライト性能がVMwareを上回る幅はわずかだ。
もしNFSを使える選択肢があるなら、使うべきだ。繰り返すが、リード性能の方がライト性能よりもはるかに重要だからだ。
ハイパーバイザーのリード/ライト性能は素晴らしい(ずるをしているからだが)。このデータのおかげで、今後はVagrantの新しい同期フォルダの実装として、ネイティブなファイルシステムだけを使うもの(rsyncや、ホストマシンをNFSサーバーではなくクライアントとして使う方法など)に一層注力していくつもりだ。
よりすぐに役立つ話としては、もし開発に仮想マシンを使っているなら、可能であればデータベースファイルを共有ファイルシステムの外に移動することだ。おそらく大きな性能向上が見られるはずだ。
最後に、この結果に大きな驚きはないと思っている。Vagrantは2010年からNFS同期フォルダをサポートしてきた。共有フォルダの性能が悪いことは早い段階で気づいていたからだ。ただ、異なる挙動を示す確かなデータがあるのはありがたいことだし、それぞれのシステムが内部で何をしているのかについて興味深い洞察も得られる。
記事をランダムに読む
コメント
ログインしてコメントする