最近、コードを書くとき、keyword 引数を使うようになってきたんだけど、
def foo(a: true) do_something if a end foo(a: false)
のつもりで、
def foo(a = true) do_something if a end
と書いてしまって、foo(a: false) とやっても a は Hash object {a: false} になってしまい、偽にならなくて困ったという話。なんとなく動いちゃってるから、よくわからなかったという。
オプショナル引数禁止、とかできるといいのかもしれないな。
仮想マシン上で TSC (time stamp counter) がどうなるか、という話。
てっきり、CPU の物理 TSC が返るのかと思ったら、ちゃんと VT-x では trap するようになっているようで。
#if defined(__GNUC__) && defined(__i386__) typedef unsigned long long tick_t; static inline tick_t tick(void) { unsigned long long int x; __asm__ __volatile__ ("rdtsc" : "=A" (x)); return x; } #elif defined(__GNUC__) && defined(__x86_64__) typedef unsigned long long tick_t; static __inline__ tick_t tick(void) { unsigned long hi, lo; __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); return ((unsigned long long)lo)|( ((unsigned long long)hi)<<32); } #elif defined(_WIN32) && defined(_MSC_VER) #include <intrin.h> typedef unsigned __int64 tick_t; static tick_t tick(void) { return __rdtsc(); } #else /* use clock */ typedef clock_t tick_t; static inline tick_t tick(void) { return clock(); } #endif int main() { volatile int n = 0x100000; int i; for (i=0; i<n; i++) { tick(); } } #if 0 $ gcc -O0 rdtsc.c && time ./a.out 仮想マシン(VirtualBox on Windows): real 0m1.744s user 0m1.740s sys 0m0.000s 同じマシンでのVC: real 0m0.049s user 0m0.000s sys 0m0.015s 別の実機(Debian/Squeeze): real 0m0.039s user 0m0.040s sys 0m0.000s #endif
明らかに結果が違う。
Stack overflow で、Why is RDTSC a virtualized instruction on modern processors? では、同じような質問をされているんだけど、accuracy が重要なんだよ、とか、そういう話。
side-channel attack というか、VM 上で動いているかどうかの判定に使われないようにする、っていうのも、結局 rdtsc が 30 倍程度遅くなることがわかってしまうので、無理なんじゃないかなぁ。
offsetting を VM-exitting ごとに適切に再設定すれば、RDTSC 命令自体は、CPU 1 命令で済むのかと思ったけど、offsetting の仕様を適切に理解できていない気もする。
元々、clock_gettime() がえらい遅い、ということで調べ始めたのだけど。VM 上の時間取得は大変(鬼門)だなぁ。準仮想化のターゲットにしないのかしら(ホスト側の設定値がそのまま見える、的な)。