はじめに
2017/03/04に書いた記事(「LinuxのCPU使用率の%stealについて」)に思いのほか反響があったので、KVM以外で私が知っていることをダンプしておくことにした。
若干TBDが多いのはご容赦願いたい。
Xenの場合
Xenの場合は普通に %steal にカウントされる。
Ubuntu Xenial の linux-4.4.0系の場合は、前回触れた account_steal_time()
が少し違うルートから呼ばれる。こんな感じ。
timer割り込み =>
=>xen_timer_interrupt() (arch/x86/xen/time.c)
=>do_stolen_accounting() (arch/x86/xen/time.c)
=>account_steal_ticks() (kernel/sched/cputime.c)
=>account_steal_time() (kernel/sched/cputime.c)
見てわかるとおり、この時点ではXenの依存コードのtimer処理部分から直接呼び出される変則的な形になっている。ただし、前の記事(の更新版)でコメントをいただいたように、現時点のLinusのtreeでは、Xen用の steal_clock ハンドラが実装されており、KVMと同じすっきりした call tree になっている。
余談だが、2008年くらいに Xen 上でWeb3層システムの検証をしていたときに、高負荷状態になるとVMの中で計測されるCPU使用率の値の精度が悪くなる現象を見たことがあった。おそらく Linus の tree を使えば sched_clock ハンドラ(xen_clocksource_read()
)も実装されているため、改善されているのではないかと想像している。
ESXiの場合
ESXi の場合は、現時点のLinusのtreeを使っても %steal に値は入らない。
(前述のXen上の検証と前後して)2007-2008年くらいに、ESXi (VI3の時代。当時はまだi(愛?)がなかった)上でLinuxベースのWeb3層システムの検証をしたことがあった。この当時、高負荷状態になるとVMの中で計測されるCPU使用率の値が狂うのでどうしようか検討していたのだが、%steal は0のままだったので意識していなかった。
では、%steal 相当の情報を得られないのか?と言われれば、実は当時でも可能だった。
まず、ESXiの vmkernel 側では、VMごとにCPU時間をaccountingしており、esxtop 等を使うと、VMごとの各種モードのCPU使用率も採取できる。この中に %Ready という値があり、これがVM側のLinuxの中でみた %steal に対応するものである。%Readyについては、今は広く知られているようだ。たとえば以下のような記事とか。
- https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2019905 (日本語)
- https://kb.vmware.com/selfservice/search.do?cmd=displayKC&docType=kc&docTypeID=DT_KB_1_1&externalId=2001003 (英語の元記事)
ではさらに、ハイパーバイザに乗り込まないとこの情報は得られないのか?といえば、実はこれも可能である。VMware社から提供されている "vSphere vSphere Guest SDK" を使うと、VMの内部でハイパーバイザから自VMが使ったCPU時間の内訳を取得することができる。
(2017/03/18追記: 追跡調査の結果、2008年当時は以下で説明する StolenMsという量は得られなかったことがわかった。記憶違いをお詫びして訂正したい。この値が取得できるようになったのは2009年のESX4.x用の Guest SDK 4.0からである)
SDKの仕様としては、現行では
からたどれる、
あたりに関連APIの説明がある。
ざっくり使い方を説明すると、初期化APIの VMGuestLib_OpenHandle()
でハイパーバイザと接続した後、定期的に VMGuestLib_UpdateInfo()
で統計情報を取得更新した後、必要なアクセサAPIで情報を取り出す。
今回の話に関連するものとしては、たとえば以下の3つがある。
-
VMGuestLib_GetElapsedMs()
- VM起動以後の実経過時間の積算値(milisec単位)
-
VMGuestLib_GetCpuUsedMs()
- VM起動以後の実CPU使用時間の積算値(milisec単位)
-
VMGuestLib_GetCpuStolenMs()
- VM起動以後の時間泥棒さんに盗まれた(笑)実時間の積算値(milisec単位)
適当な間隔で2回情報を採取し、1. の差分を分母に、3.の差分を分子に使って前回説明した計算を行えば %steal 相当の値を得ることができるのがわかると思う。
若干手前味噌だが、当時作ったものが以下においてある。
VI3時代に作ったので、今はビルドにちょっと手直しが必要かもしれない。
(2017/03/11追記: 案の定動かなかったので、open-vm-tools 前提に手直ししておいた)
なお、こんなI/Fがあるのであれば、Linux kernel からも取得できるようにすればよいと思うかもしれない。しかし、この vSphere Guest SDK は user land から使うものである上にソースが公開されておらず、I/Fがわからない 1 ので、VMwareの人にまかせるしかなさそうだ。
(2017/03/11追記: 実は、VMware Tools のOSS版の open-vm-tools には、Guest SDK相当のコードが含まれていることがわかった。別途記事を書きたいと思う)
(2017/03/12追記: 上記のvgstatを手直ししながら、2008年当時は VMGuestLib_GetCpuStolenMs()
は提供されておらず、%Ready相当の値を知る方法はなかったのではないか?という気がしてきた。これも含めて別記事にまとめたい)
ちなみに、現時点のLinusのtreeでは、steal_clock ハンドラは存在しないが、sched_clock ハンドラ(vmware_sched_clock()
)は実装されており、ハイパーバイザからTSCを取得できるようになっている。
Hyper-Vの場合
Hyper-VでもESXiと事情は同じで、現状 Linus のツリーを持ってきても、%steal に値は入らない。
なお、白状しておくと、Hyper-Vについてはソースを追っただけで自分で検証していない。(ずっと、やりたいとは思っているのだが...)
ぐぐって出てきたのが以下の記事で、ずばり、Hyper-VでESXi の %Ready に対応するのって何よ?という記事である。
これによると、少なくとも Windows Server 2012/2012R2 では、perfmon (?)に "Hyper-V Hypervisor Virtual Processor\CPU Wait Time Per Dispatch " というカウンタがあり、これが対応するらしい。名前からすると、百分率ではなく、積算値(vSphere Guest SDKで言うところの StolenMsに対応)のようだ。
そのほか、こんな記事もみつけたのだが、同じカウンタに触れているようだ。
- http://unix.stackexchange.com/questions/93168/measuring-cpu-steal-on-vmware-and-hyper-v-hypervisors/295186
- http://serverfault.com/questions/392216/is-there-a-windows-equivalent-of-unix-cpu-steal-time#455554
ところで、Ubuntu Xenial のlinux-4.4.0 系kernelの時点では、仮想デバイスまわりの対応のみ含まれているようだ。もうひとつ、KVMのHyper-V emulation なるコードが入っているのだが、あれはなんだろう?これはTBD。
また、本稿執筆時点のLinusのtreeを眺めると、 steal_clock ハンドラも sched_clock ハンドラも未実装のようだ。ただ、上記のようにHyper-V側では accounting を行っているため、いずれは実装されるものと思われる。
s390の場合
こんな書評を書いた都合上、s390に触れないわけにはいかないとは思うのだが、時間の都合で TBD。
PowerPCの場合
kernelのソースを調べていた際に、PowerPCの場合も何か独自の考慮が入っていることに気づいたのだが、これも未調査。(需要があるのかどうかもわからないし)TBDということで。
まとめ
- XenはだいたいKVMと同じ。
- ESXi と Hyper-V はハイパーバイザから%steal相当の時間泥棒情報を取得することが可能。現時点では、kernelでは未サポートだが、必要な情報はハイパーバイザ側にあるため、いずれ実装されるのではないかと思われる。
- 課題/TBD
- s390 と powerpc はナニカをしている。
- そのほかたくさん (fade out...)
-
リバースしても組み込めないので、それは言わない。 ↩