結論
-> vmwareを使うと速い
経緯
私達のチームでは、開発環境と本番環境の差をなるべく無くすために、VagrantとDockerを使って環境を構築しています。Vagrantで動作しているのはUbuntu 14.04 x64です。VirtualBoxにはGuest Additionsがインストールされている状態です。
ある日、同僚からdockerコンテナでScalaのソースをコンパイルすると遅すぎるとの苦情がきたのでどこが遅いか調べてみることにしました。
どのくらい遅いかというと、macでコンパイルすると6秒で完了するものが、Dockerコンテナ内だと30秒かかる。5倍ぐらい時間がかかってます。
Dockerコンテナが遅いのか? -> 遅くない
まずDockerコンテナが遅いのかどうかを知らべてみることにしました。
そのために同じScalaの環境をゲスト環境(Ubuntu 14.04)にも構築して実行してみると、Dockerコンテナと差はなく30秒ほどかかります。少なくともDockerコンテナが遅いということでは無いということが判明しました。
VirtualBoxが問題なのか?
ということは、VirtualBoxで走らせてるからここが問題だろうということで、I/O APICをオンオフしたり、VT-xをオンオフしてみたりとVirtualBoxのパラメタを調整してみましたが変化は確認されず、案の定余計遅くなったりしました。割り当てCPU数は2CPUsから4CPUsまで試しましたが、3CPUsでは1〜2秒程早くなるものの抜本的解決には至りませんでした。4CPUsでは逆に遅くなることがありました。mac側の物理コア数が4つなのでこれ以上は試していません。メモリも同様に1G〜2Gと試してみましたが変化なし。
VirtualBoxが遅かった
これはもうVirtualBoxが遅いんだろう、ということで試しにVMWareの形式にコンバートして実行してみると、Scalaのコンパイルは6秒で完了するではないですか! 仮想化のオーバーヘッドが多少あるだろうと思うのですが、厳密なベンチマークを取得していないので詳細はわからないのですが、少なくとも体感的にはVirtualBoxより断然速いです。
いままでVirtualBoxがそこまで遅いとは思ってなかったけど、コンパイルのような重い処理を実行させると処理速度の遅さが顕著に表われました。
VagrantのVMWareプロバイダ
Vagrantは、有料のオプション(いまは$79)でVMWareプロバイダを使うことができます。
ライセンスを購入すると、license.licファイルが送られてくるので、下記コマンドでプラグインとライセンスを認識させます。
vagrant plugin install vagrant-vmware-fusion
vagrant plugin license vagrant-vmware-fusion license.lic
plugin install vagrant-vmware-fusionは、jsonの拡張をコンパイルするために、command line toolsが必要です。インストールされていない場合は、xcode-select --install
としてインストールします。
しかし現在のvagrant 1.6.3ではvagrantcloudから取得したvmwareのboxは、vmware_desktopと認識されてしまうようで、vmware_fusionプロバイダでは実行できないよ、と怒られてしまいます。
The box you attempted to add doesn't match the provider you specified.
Provider expected: vmware_fusion
Provider of box: vmware_desktop
これは直接box addすることで回避できました。この問題は修正中のようです。
追記: 1.6.5で修正されていました。
wget https://vagrantcloud.com/reoring/ubuntu-14.04-with-docker/version/5/provider/vmware_fusion.box
vagrant box add ubuntu vmware_fusion.box
boxファイル
今回VirtualBoxとVMWareに使ったBoxファイルはvagrantcloud/reoring/ubuntu-14.04-with-dockerで公開しています。
packer
このboxファイルは、packerを使ってビルドしています。github/reoring/packer-ubuntu-14.04-docker
おまけ
Vagrantfileでvmwareのcpu数とメモリ数を設定する方法
config.vm.provider "vmware_fusion" do |v|
v.vmx["memsize"] = "1024"
v.vmx["numvcpus"] = "2"
end