BitVisorに限らず、VMMと仮想マシン(VM)の間のコンテキスト切り替えにはどうしても時間がかかります。その時間を簡単なプログラムを使って推測する方法を紹介します。
CPUID命令の実行時間を測るプログラム
VM上でのCPUID命令の実行は、様々な理由によりVMMで処理されます。そこで、CPUID命令の実行時間を測ることで、切り替え時間を推測します。プログラムは以下のような簡単なものでOKです。これはタイムスタンプカウンターを使って時間を計算します。
#include <stdio.h>
#define N 65536
typedef unsigned long long l;
l t[N];
l min(l i,l j){for(;i<N;i++)if(t[j]>t[i])j=i;return t[j];}
l max(l i,l j){for(;i<N;i++)if(t[j]<t[i])j=i;return t[j];}
l avg(int i,l s){for(;i<N;i++)s+=t[i];return s/N;}
int main(){
for(int i=0;i<N;i++)
asm volatile("rdtsc\nmov %%edx,%%esi\nmov %%eax,%%edi\nxor %%eax,%%eax\n"
"cpuid\nrdtsc\nsub %%edi,%%eax\nsbb %%esi,%%edx\n"
"shl $32,%%rdx\nor %%rdx,%%rax":"=a"(t[i])::"%rbx","%rcx",
"%rdx","%rsi","%rdi");
return printf("min:%llu avg:%llu max:%llu\n",min(0,0),avg(0,0),max(0,0));
}
実行例
AMD Ryzen 7 2700を搭載したPCで実行してみました。
VMMなし
$ ./a.out
min:288 avg:290 max:33664
$ ./a.out
min:288 avg:292 max:132896
$ ./a.out
min:288 avg:290 max:15744
$ ./a.out
min:288 avg:290 max:13536
$ ./a.out
min:288 avg:292 max:100128
BitVisor
$ ./a.out
min:1856 avg:2403 max:271136
$ ./a.out
min:1792 avg:2421 max:285280
$ ./a.out
min:1856 avg:2328 max:357440
$ ./a.out
min:1856 avg:2395 max:415040
$ ./a.out
min:1856 avg:2322 max:381376
$ ./a.out
min:1856 avg:2354 max:361408
Linux KVM
$ ./a.out
min:1984 avg:2778 max:1153408
$ ./a.out
min:1983 avg:3003 max:3459008
$ ./a.out
min:1984 avg:2688 max:5033312
$ ./a.out
min:2240 avg:2644 max:123200
$ ./a.out
min:1952 avg:2751 max:4580448
$ ./a.out
min:1952 avg:2807 max:4342624
$ ./a.out
min:2271 avg:2452 max:482400
Linux KVM on BitVisor
$ ./a.out
min:7776 avg:8373 max:404096
$ ./a.out
min:7616 avg:8677 max:384768
$ ./a.out
min:7551 avg:8558 max:5422400
$ ./a.out
min:7616 avg:8505 max:5865856
$ ./a.out
min:7552 avg:8561 max:5930400
推測
VMMなしの状態で最低でも290クロックくらいかかるというわけですから、他の結果からその数字を引けば残りは切り替え等に要した時間と推測できそうです。つまりBitVisorは1600クロックくらい、Linux KVMは1700クロックくらい、BitVisor上のLinux KVMは7200クロックくらい切り替えにかかっていると言えそうです。
このプログラムはIntelプロセッサの環境でも使えますのでぜひ試してみてください。