KVM 上の Windows7 をチューニングする

# 動機
[前回](http://qiita.com/flny/items/5c55c2dfa3f43b31aa5b) Docker + KVM で作成した仮想マシンにWindows7 をインストールしましたが、インストール自体やOSの起動はとても早いものの、いざ使ってみるとかなりモッサリしています。このままだと実使用には耐えないと思い、パフォーマンスの改善を試みることにしました。

# 現状を知る
まずは Windows エクスペリエンス インデックスを見てみます。![exp.png](https://qiita-image-store.s3.amazonaws.com/0/87156/3549ebc6-cf3b-30d9-4967-64c5e0ee57a4.png)
1.0とか初めて見たんですけど...。ビデオカードをエミュレートするのが重いのでしょうか。それ以外のリソースは問題ないようです。

# QXLドライバを利用する
調べたところ、```-vga qxl```を指定しつつSPICEでKVMに接続している状況下では、ゲストOSでQXL用のデバイスドライバを利用すると描画性能が向上する(本来のパフォーマンスを発揮する)ようです。
[参考資料1](http://i.sios.com/products/oss/redhat/tech_news/2012/12/20127kvm-spice.html), [参考資料2](http://www.atmarkit.co.jp/ait/articles/1006/29/news083_2.html)

## QXLドライバをダウンロードする
[こちら](http://www.spice-space.org/download.html) の Guest -> Windows binaries -> [Windows QXL driver](http://www.spice-space.org/download/windows/qxl/qxl-0.1-21/) にWindowsゲスト用 QXLドライバがありますので、これをダウンロードします。Windows7の32bit版([qxl_w7_x86.zip](http://www.spice-space.org/download/windows/qxl/qxl-0.1-21/qxl_w7_x86.zip))です。zipファイルをダウンロードしたら解凍して適当なディレクトリに置きます。

## QXLドライバをインストールする
デバイスマネージャから ディスプレイ アダプター -> 標準 VGA グラフィックアダプター を選択し、ドライバーの更新 を選択します
![driver_up1.png](https://qiita-image-store.s3.amazonaws.com/0/87156/fabe04d0-05c4-1fb0-c623-35aa258de06e.png)

解凍したファイルを置いたディレクトリを指定して、ドライバを更新します。![driver_up2.png](https://qiita-image-store.s3.amazonaws.com/0/87156/47b86509-5764-5032-5d67-d1bf2df189a7.png)

ドライバ署名が云々、みたいな問題も発生せず、インストールできました。

## 結果を確認する
ゲストOSの再起動後、結果を確認してみます。既にマウスカーソルの動きが機敏に感じるのですが、気のせいかもしれないので エクスペリエンス インデックス を更新します。
![exp2.png](https://qiita-image-store.s3.amazonaws.com/0/87156/72afc873-ed8d-5099-1d2e-2516d93275af.png)
変わってねぇ！ ...ですが体感では明らかにモッサリ感がなくなったので ヨシとします。


# サウンドカードを変更する[^1]
デバイスマネージャを開いたときに気づいたのですが、```-device AC97``` で仮想サウンドカードを追加したものの Windows7にドライバが含まれていないようで、動作していませんでした。仮想サウンドカードを別のものに変更し、音が出るようにします。
![ac97.png](https://qiita-image-store.s3.amazonaws.com/0/87156/9998148d-0ddd-17c0-7376-deb36e126cf5.png)


## KVMの起動パラメータを変更する
docker-compose.yml を編集して、```-device AC97``` を```-device intel-hda -device hda-duplex``` へ変更します。

## 動作を確認する
KVMを再起動して動作確認します。
まずはゲストのWindows7をシャットダウンします。このときKVMとともにDockerコンテナが停止するため、```$ docker-compose up -d windows7``` でコンテナを再作成します(同時にKVMが起動します)。
SPICEクライアントから Windows7に再接続してデバイスマネージャを見ると、変更後の仮想サウンドカードが正しく認識されていました。
![hda.png](https://qiita-image-store.s3.amazonaws.com/0/87156/f515619d-f04e-9020-6b8b-1e81369a8290.png)

Windows7で再生された音が、SPICEクライアントでも再生されるようになりました。

# virtioを利用する
(4/2追記 @tukiyo3 さんのコメントより)
仮想ディスクへの接続を[準仮想化ドライバ](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Virtualization_Host_Configuration_and_Guest_Installation_Guide/chap-Virtualization_Host_Configuration_and_Guest_Installation_Guide-Para_virtualized_drivers.html)であるvirtioに変更して、ディスクパフォーマンスの改善を試みます。

変更前のベンチマークはこんな感じです。
![before.png](https://qiita-image-store.s3.amazonaws.com/0/87156/688a369d-1a2b-a6f0-748c-f4a938614b60.png)


## ドライバを準備する
[こちら](https://fedoraproject.org/wiki/Windows_Virtio_Drivers)からドライバの入った[イメージファイル](https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso)(ISO)をダウンロードします。

```
$ wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso
$ mv virtio-win.iso /mnt/vm/windows7/
```

また、追加の仮想ディスク temp.raw を作成しておきます。

$ dd if=/dev/zero of=/mnt/vm/windows7/temp.raw bs=10M count=100


## ドライバをインストールする

docker-compose.yml を編集して 

- ダウンロードしたイメージファイルをCDROMとして、
- 作成した仮想ディスク temp.raw をHDDとして、仮想マシンに追加します。

このとき、temp.raw のみ接続インタフェースをvirtioとします。(if=virtioの部分)
if=virtioを記述すると、-hda, -hdb, -cdrom のオプションは使えなくなるためこれらは全て -driveに統一する必要があります。[^2]

```yaml:docker-compose.yml
  command: "/run.sh  \
(略)
    -drive file=/mnt/vm/windows7/virtio-win.iso,media=cdrom \
    -drive file=/mnt/vm/windows7/primary.raw \
    -drive file=/mnt/vm/windows7/temp.raw,if=virtio"
```

この状態でコンテナを作成し、Windows7を起動します。

![drives_before.png](https://qiita-image-store.s3.amazonaws.com/0/87156/b3340cc9-a69a-ad00-7045-49a073aad143.png)
![volumes_before.png](https://qiita-image-store.s3.amazonaws.com/0/87156/db6d3154-7db8-594d-b604-4b91e7d83c8b.png)

virtio-win.iso は正しくマウントされましたが、temp.rawのほうは virtio接続のドライバが未インストールであるため正しく認識されていません。

デバイスマネージャを見ると、virtio接続が 謎のSCSIコントローラーとして追加されているので これに対してドライバをインストールします。
![devices_before.png](https://qiita-image-store.s3.amazonaws.com/0/87156/85fdd5c3-c3bd-dcaf-c914-13c5a4452e0b.png)

1. そのままデバイスマネージャの SCSIコントローラー をダブルクリック
2. ドライバの更新 を押下
3. コンピュータを参照してドライバソフトウェアを検索
4. E:\viostor\w7\x86 [^3] を選択して 次へ
5. Red Hat VirtIO SCSI controller が見つかるのでインストール

4のドライバのありかを指定する部分については、x86まで明示的に指定したほうがよいようです。(E:\を指定したらBSODになりました。誤って64bit版が選択される?)
![install.png](https://qiita-image-store.s3.amazonaws.com/0/87156/f50349fb-7e2a-2c17-e5a9-789a1f9f368e.png)

![devices_after.png](https://qiita-image-store.s3.amazonaws.com/0/87156/91402169-6a12-09a6-3097-8371b9859c99.png)

インストールが完了したら、一旦仮想マシンをシャットダウンします。

## virtioを有効化する

元々あった仮想ディスク(primary.raw)をvirtio接続に変えつつ、ドライバインストール用に追加した仮想ディスク(temp.raw)とCDROM(virtio-win.iso)を削除します。

```yaml:docker-compose.yml
  command: "/run.sh  \
(略)
    -drive file=/mnt/vm/windows7/primary.raw,if=virtio"
```

再度 Windows7を起動したところ 問題ないようです。ベンチマークを取ります

![after.png](https://qiita-image-store.s3.amazonaws.com/0/87156/c69c66a9-59cd-9427-33df-936b275e6f97.png)

劇的な効果です！ 3倍以上になった数値もあります

以上

[^1]: 全然チューニングじゃなくてスミマセン

[^2]: -cdrom file=hoge.iso としてしまうと、```qemu-system-x86_64: -cdrom file=hoge.iso: could not open disk image file=hoge.iso: Could not open 'file=hoge.iso': No such file or directory``` というエラーが出ます。非常にわかりにくいというかハマりました
[^3]: 64bit版のWindows7なら x86の部分はamd64になります。