Hyper-Vの準仮想化クロックのしくみ

準仮想化クロックについていろいろ調べてみて、Hyper-Vでは何をやっているのだろうと疑問に思いました。

そこで、LinuxのHyper-V用準仮想化クロックのドライバを見てみることにしました。

準仮想化クロックは、ソースコードLinux/arch/x86/kernel/cpu/mshyperv.cで、hyperv_clocksourceという名前で登録されています。

しくみについて簡単にコメントがありました。MSRというCPU内部のレジスタにHV_X64_MSR_TIME_REF_COUNTという名前のレジスタがあります。そのレジスタを読むとパーティションカウンターという数値が読めます。これは、子パーティション(ゲスト)が作られてからのtick countという値です。このcountは、子パーティションが作られたとき0になり、100 nanosecond単位で増加します。

要するに子パーティションができてからの時間が分かります。

これで、ゲスト起動時に時刻が設定されていれば現在時刻を計算することができます。

後はどれくらいの頻度で値が更新され、どれくらいの頻度で見に行くのかですが、Windowsで何をやっているのかですね。

意外にシンプルなことをやっていますね。その分kvm-clockと比べて少し精度は落ちるのかもしれません。起動してからの経過時間を使って時計を正確にしようとしているのは、LinuxとWindowsで似ていて面白かったです。

Hyper-Vについて書かれたKVMの資料
KVM as a Microsoft-compatible hypervisor.

Hyper-Vのインターフェースについて書かれた公式資料
Requirements for implementing the Microsoft Hypervisor interface

準仮想化クロックを使用しているときのUbuntuゲストのNTP使用とSUSEの場合について

準仮想化クロック(kvm-clock)を使用しているとき、UbuntuゲストでNTPを使用しなくてもいいというような記事がありました。

それでいろいろ調べてみました。ところが、よく見るとUbuntuのWikiのヘルプページはひんぱんに書き換えられているらしいです。最近のヘルプではUbuntuをゲストOSに使っているときもNTPを使ったほうがよいと書いてあります。ゲストでNTPを使わなくてもkvm-clockは正確だそうです。

KVM/FAQ

kvm-clockだけ正確でもシステムクロックが正確にならないと意味ないと思うのですが、後は自分でやってねというスタンスでしょう。

kvm-clockは、システムが起動してからの経過時間を供給しますが、閏秒などの情報を供給しません。

というわけで、kvm-clockを使っているときも時計を正確にしたければNTPを使いましょう。

SUSEのマニュアルだと、ゲストに使ったときはNTPを使わないようにという説明があるのですが、理由がはっきりしません。

Xenの場合はカーネルパラメータにxen.independent_wallclockがあります。これを使う場合はNTPを使うと2重に時計を管理することになり不具合が出るという報告があります。

また、Xenを使っているときでも、xen.independent_wallclock=1にしてNTPを使ったほうがいいというメールもあります。

sistemad telling me "Time has been changed", only on xen guests?

システムクロックを同期する方法が他にあるかと思いましたが、いくら検索してみても情報が出てきません。NTPなしで使用してみて問題が出るようであればNTPを使ったほうがいいと思います。kvm-clockのしくみから見ても、そのほうが自然です。

準仮想化クロックkvmclockのしくみ

準仮想化クロックのしくみについて解説してるブログがありました。

KVM pvclock

まず、ゲストOSが読めるメモリーをMSRを使って登録しておきます。そこへKVMがホストの起動してからの時間とTSC(Time Stamp Counter)を書き込みます。ゲストOSは時間を知りたいときに、まず現在のTSCを読みます。そして、メモリー上の起動してからの時間とTSCの差分の値を使って現在時間を割り出します。

ホストの起動したときの時刻は別に保存してあるそうです。

メモリーを使って値のやり取りをしていることと、TSCを使っているのが特徴かなと思います。

メモリーの値がアップデートされるのはホストOSからゲストOSに制御が移るVM eventの前だそうです。

時計がどれだけ正確化は、ゲストOSがどういうタイミングで時計をチェックして更新するかによります。
Linuxのシステムクロックについては、こちらの解説がくわしいです。4回の連載になっていて、kvm-clockについてもpvclockとして解説があります。
kvm-clockはRTCのようにハードウェアクロックの1種とされているようですが。

ハードウェアの時計とシステムクロックの同期は、システムの起動時とサスペンド、レジューム時に行われるそうです。その他に、getnstimeofday()/ktime_get_real()はハードウェアの時計も参照するとなっています。、gettimeofday()はハードウェアの時計を参照するようです。

カーネルにおけるタイマー事情 ~第3回 IAマシンのもつ各種計時ハードウェア~

準仮想化クロックを使っているときは、ホストOSにNTPを動かしていることが大切ですね。ゲストOSで動かしたほうがいいかどうかはディストリビューションによって意見が分かれるようです。

KVMにおいて ホストとゲストの時間管理はNTPを用いるべきか?

ゲストOSでNTPを使わなかった場合、ハードウェアの時計であるkvm-clockをゲストOSのシステムクロックに反映させる必要があります。UbuntuやSUSEにそういう仕組みがありましたっけ。確認が必要です。

以上簡単ですが準仮想化クロックについて調べてみました。

追記
ハードウェアクロックというとRTC(Real Time Clock)のことを指すそうです。kvm-clockは、ハードウェアの時計と書き直しました。

追記(2015/08/09)
KVMがメモリに値を書き込む頻度についてLinuxのカーネルソースを調べたところ、そう頻繁には値が更新されていないことがわかりました。

VirtualBox 5.0の準仮想化クロックの速度測定

VirtualBox 5.0の準仮想化クロックをgettimeofday()を使って測定された方がいらっしゃいました。

VirtualBox 5 で利用可能になった Paravirtualization 機能 kvmclock を使う

kvm-clockは、TSC(Time Stamp Counter)より2倍くらい遅いそうです。

TSCはCPUが刻んでいるタイマーです。タイマーとしては一定のリズムを刻んでほしいのです。しかし、昔のCPUではCPUがスリープモードになったりして周波数を落とすと、一緒になって遅くなってしまうことがあったそうです。最近のCPUでは大丈夫なようですが。また、TSCの値がCPUのコアごとに少しずつずれてしまうのです。それで、なかなか安定したタイマーとしては使いにくいのです。

調べてみると、kvm-clockもTSCを使っています。詳しくは次の記事に書きます。

VirtualBox 5.0のSMPスピンロックの確認

VirtualBox 5.0では、Linuxゲストに対してKVMタイプとして準仮想化クロックとSMPスピンロックが提供されます。

今回は、SMPスピンロックを確認してみます。

ベンチマークとしてUnixBench 5.1.3を用いました。

準仮想化インターフェースで”なし”と”KVM”を選んでそれぞれUnixBenchを走らせます。

ゲストOSはUbuntu 12.04で仮想CPUを2CPUで行いました。

まずはUnixBenchをダウンロードしてきて解凍しベンチマークを走らせます。
-iというオプションは測定を各項目で1回に制限するものです。そうしないと、10回やってしまい30分くらい時間がかかります。

wget https://byte-unixbench.googlecode.com/files/UnixBench5.1.3.tgz
tar xvzf UnixBench5.1.3.tgz
cd UnixBench
./Run -i 1

準仮想化インターフェースを変えても結果はあまり変わらなかったのですが、Index Scoreと特に値が大きく変わったPipe-based context switchingをまとめました。

Index Score

準仮想化インターフェース 1CPU 2CPU
なし 1739.7 2912.0
KVM 1910.0 3278.5

Pipe-based context switching

準仮想化インターフェース 1CPU 2CPU
なし 329.3 565.5
KVM 919.5 1814.0

Pipe-based context switchingというのは、プロセスのコンテキストスイッチを起こさせることでOSとCPUの性能の違いを見るものです。コンテキストスイッチとは、複数のスレッドやプロセスの実行の順番を変えて実行することです。

準仮想化インターフェースにKVMを選ぶことで565.5から1814.0と3倍くらい性能が上がっていることが分かります。

Index Scoreの値が変わったのは主にPipe-based context switchingが変わったことによるものです。

ただ、実際にこの違いが分かるかというと、マルチスレッドのプログラムをぶん回したりサーバーで複数のプロセスを高負荷で動かすことをしないと実感できないと思います。

以上、VirtualBox 5.0のSMPスピンロックについて確認してみました。

OpenStackでできること、変わること

OpenStackのセミナーの様子が報告されています。

「分かる、できる、本当に使える、OpenStack超入門」セミナーリポート~ユーザー、ベンダーが本音で語った「できること、変わること」~ (1/3)

報告をピックアップしてみると次のようになります。

バージョンアップは負担になる。まずは使ってみること。

コスト意識は大切。OpenStack APIが使えればベンダーロックインは避けられる。

小さく始めて大きく育てること。

とにかく自動化すること。とにかくテストすること。手動で行わないことが大切です。

バージョンアップの問題は実例がそろい出したところです。

企業文化を変えることが必要です。

導入にはそれなりに学習コストがかかることが分かります。企業文化を変えることも思わぬ障害になるかもしれません。今まで慣れてきた「動いているものは触るな」という文化にはそぐわないものですので。まずは使ってみることというのが一番初めにやることかなという気がします。

VirtualBox 5.0の準仮想化クロック

VirtualBox 5.0が登場しました。

VirtualBox

プレスリリースによると次のような特徴があります。

  • WindowsとLinuxゲストの準仮想化のサポート
  • CPU使用の改善。CPUの命令が増えています。
  • USB 3.0のサポート
  • Windowsのドラッグアンドドロップのサポート
  • ディスクイメージの暗号化

Linuxゲストの準仮想化をサポートするというので、早速インストールしてみました。

前回にも書きましたが、Linuxゲストの準仮想化はXenのように準仮想化専用のカーネルを動かすのではなく、準仮想化インターフェースに機能を提供してエミュレーションの精度をあげるものです。

Linuxゲストには、KVMタイプとして準仮想化クロックとSMPスピンロックが提供されます。この準仮想化クロックを確認してみます。

今回はUbuntu 12.04ゲストで確認しました。

まずは順番にインストールしていきます。

  • VirtualBox 5.0のインストール
  • Extenstion Packのインストール
  • ゲストOSを起動してGuest AdditionsをゲストOSにインストール
  • 一度シャットダウンして、仮想マシンの設定で、システムー>アクセラレーション準仮想化インターフェースで、KVMもしくはデフォルトを選びます。デフォルトはゲストOSのタイプによって提供するインターフェースを変えてくれます。
  • ゲストOSの起動

起動したら、dmesgで起動時のメッセージを確認します。

$ dmesg |grep KVM
[ 4.515926] Booting paravirtualized kernel on KVM

このようにon KVMとでていれば成功です。

同様にkvm-clockを確認することで準仮想化クロックを使っていることが分かります。

$ dmesg |grep kvm-clock
[ 0.000000] kvm-clock: Using msrs 4b564d01 and 4b564d00
[ 0.000000] kvm-clock: cpu 0, msr 0:1cf9781, boot clock
[ 4.516128] kvm-clock: cpu 0, msr 0:7fc12781, primary cpu clock
[ 4.730889] kvm-clock: cpu 1, msr 0:7fd12781, secondary cpu clock
[ 4.798499] Switching to clocksource kvm-clock

もし、kvm-clockなんて出てこなかったらkvm-clockがシステムに存在するか次のように調べます。

$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
kvm-clock tsc acpi_pm

もし、なければカーネルにCONFIG_PARAVIRT_CLOCKが設定されていたか調べます。

$ less /boot/config-hogehoge
CONFIG_PARAVIRT=y
CONFIG_PARAVIRT_SPINLOCKS=y
CONFIG_PARAVIRT_CLOCK=y

こうなっていなければ、準仮想化クロックは使えません。CONFIG_PARAVIRT_CLOCKがあって、kvm-clockがないときは、VirtualBoxがインターフェースを提供できていないです。

準仮想化クロックを使うことで時間の精度が上がります。でも、ゲストOS上でもNTPを使ったほうがよいようです。

KVMにおいて ホストとゲストの時間管理はNTPを用いるべきか?

準仮想化クロックと共に提供されるSMPスピンロックはマルチCPUでたくさんのプロセスを同時に起動したときの効率を高めてくれるものです。

ベンチマークを取らないと確認できないと思います。

ネットワークやディスクのアクセスも改善されるのかも確認が必要ですね。

以上、準仮想化クロックについて確認してみました。

VirtualBox 5.0RC2が登場

VirtualBox 5.0のリリースが間近のようです。

VirtualBox 5.0リリース間近、RC2が登場。準仮想化でWindowsやLinuxの性能向上、USB 3.0対応など

準仮想化に対応ということで少し調べてみました。

準仮想化インターフェースという設定項目ができた。

Xenのように準仮想化のカーネルを動かすかと思ったけどそうでないようです。

マニュアルを読んでみると、ゲストOSの準仮想化機能にインターフェースを提供してエミュレーションの精度を上げるもののようです。

デフォルト、Legacy、Minimal、Hyper-V、KVMと選択項目があります。

デフォルトだと、ゲストOSのタイプによって変わります。

MinimalはTSC(タイムスタンプカウンター)とAPICの周波数をゲストOSに提供する。MacOSに推奨。

KVMだと、Linuxカーネル2.6.25以上で、準仮想化クロックとSMPスピンロックを提供する。Linuxに推奨。

Hyper-VだとWindows 7以上で、準仮想化クロック、APICの周波数の通知、タイマーのチェックの緩和。WindowsとFreeBSDに推奨。

Legacyだと何もやらないのか記述がないです。

ゲストOSの時間の問題は複雑でパフォーマンスにも大きな影響があったので、その改善に役立つのではないでしょうか。