1年に1回ぐらい、「そういえば仮想マシンではTickタイムが不正確だから、パフォーマンス試験を仮想マシン上の時計で計るのは不適切なんだったか?」と思いだすものの、実際どのくらい不正確なのかねというのは未検証で10年ぐらい過ごしてきたのだが、今回は簡単に確認するところまではたどり着き、認識を新たにした。
思いのほか正確である。constant_tscとかnonstop_tscとか、難しいことはわからないが最近の進歩の結果らしい。
要らん心配事が減るのは大変良いことだ。
検証の仕方
1.手元のWindows 10 PC(物理)で現在時刻を表示する。
2.Windows 10 PCからcurl.exeで、Linux仮想マシン上のプログラムにhttpでアクセスする。プログラムはsleepで10分(600秒)待った後、応答を返す。
3.再度、手元のWindows 10 PC(物理)で現在時刻を表示する。
4.Windows 10 PCからcurl.exeで、Linux仮想マシン上のプログラムにhttpでアクセスする。プログラムはアクセス開始からtickカウントが10分(600秒)増えたら、応答を返す。
5.最後にまた、手元のWindows 10 PC(物理)で現在時刻を表示する。
Windowsで実行する具体的なコマンドは以下。
> powershell "get-date; curl.exe http://<仮想マシンのIPアドレス>/sleep; get-date; curl.exe http://<仮想マシンのIPアドレス>/ticktime; get-date;
Linux仮想マシン上で実行し、httpリクエストを受け付けるプログラム。Ruby+sinatra。
require "sinatra"
set :bind => "0.0.0.0"
set :port => "80"
get "/sleep" do
res = ""
res += Time.now().to_s() + "\n"
res += `date`
res += "sleep\n"
`sleep 600`
res += Time.now().to_s() + "\n"
res += `date`
end
get "/ticktime" do
res = ""
res += Time.now().to_s() + "\n"
res += `date`
res += "ticktime\n"
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
while (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) <= 600.0; end
res += Time.now().to_s() + "\n"
res += `date`
end
検証1:Windows 10 PC&VMware Workstation上のCentOS 8
Windows 10 PC(物理)で動作するVMWare Workstation 16 Proに、CentOS 8.3のゲストOSを導入して実行した結果。
2021年1月29日 0:40:17 → 「1.」の時間
2021-01-28 10:40:16 -0500
Thu Jan 28 10:40:16 EST 2021
sleep
2021-01-28 10:50:16 -0500
Thu Jan 28 10:50:16 EST 2021
2021年1月29日 0:50:17 → 「3.」の時間
2021-01-28 10:50:16 -0500
Thu Jan 28 10:50:16 EST 2021
ticktime
2021-01-28 11:00:16 -0500
Thu Jan 28 11:00:16 EST 2021
2021年1月29日 1:00:17 → 「5.」の時間
一応、OSで取得した/proc/cpuinfoのCPUフラグ。
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
検証2:Amazon Lightsail上のCentOS 7
Sleepのところで一秒ずれるが、プログラム起動やhttpのオーバーヘッドもあるし、許容出来る。
2021年1月28日 23:49:21 → 「1.」の時間
2021-01-28 14:49:21 +0000
Thu Jan 28 14:49:21 UTC 2021
sleep
2021-01-28 14:59:21 +0000
Thu Jan 28 14:59:21 UTC 2021
2021年1月28日 23:59:22 → 「3.」の時間
2021-01-28 14:59:21 +0000
Thu Jan 28 14:59:21 UTC 2021
ticktime
2021-01-28 15:09:21 +0000
Thu Jan 28 15:09:21 UTC 2021
2021年1月29日 0:09:22 → 「5.」の時間
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase bmi1 avx2 smep bmi2 erms invpcid xsaveopt
検証3:IBM Cloud(Classic)上のRHEL 8
LocationをTokyoとして仮想マシン作ったのに時刻がCSTとはこれ如何に、という事に気が付いたが、まあ、時間の精度は申し分ない。
2021年1月29日 0:00:14 → 「1.」の時間
2021-01-28 09:00:13 -0600
Thu Jan 28 09:00:13 CST 2021
sleep
2021-01-28 09:10:13 -0600
Thu Jan 28 09:10:13 CST 2021
2021年1月29日 0:10:14 → 「3.」の時間
2021-01-28 09:10:14 -0600
Thu Jan 28 09:10:14 CST 2021
ticktime
2021-01-28 09:20:14 -0600
Thu Jan 28 09:20:14 CST 2021
2021年1月29日 0:20:14 → 「5.」の時間
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush acpi mmx fxsr sse sse2 ht syscall pdpe1gb rdtscp lm constant_tsc rep_good nopl cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt clwb xsaveopt xsavec xgetbv1 xsaves pku ospke md_clear flush_l1d