gcc内联汇编之rdtsc

有时会需要测试一个函数的运行时间, 用标准库的时间函数精度不够, 打印出来的运行时间是0.00000…
用循环来放大这个时间一般不会有问题的
但是如果多个算法之间时间开销差别很大, 比如函数aa()运行一次的时间是1.0s, 而函数bb()运行时间是0.000000s, 这时候再对他们用循环1000次的办法来放大时间, 这时bb()的运行时间也许刚好够打印输出, 比如是0.000010s, 那等待aa()循环1000次就得花1000s左右
这时候就需要用高精度计时器, 分别获取函数运行前和运行后的cpu时间戳, 相减就能算出函数运行需要的cpu时钟周期, 这个数字在不同的cpu上不一样, 不过只要保证每次测试是在同一台主机上测试的就没问题
以下是gcc中获取cpu时间戳的代码

static inline uint64_t get_cycle_count() {
    uint32_t time_high, time_low;
    __asm__(
            "rdtsc;"
            "movl %%edx,%0;"
            "movl %%eax,%1;"
            :"=m"(time_high),"=m"(time_low)
            :
            :"%edx","%eax"
    );
    return (uint64_t) time_high << 32 | time_low;
}

rdtsc指令是获取64位的当前时间戳(从开机开始计时), 并将高32位写入edx, 低32位写入eax
不过也不要太依赖cpu时间戳, 因为在多核cpu上不是太精确, 而且多次测试的值差别比较大…
具体原因见此文:http://blog.csdn.net/solstice/article/details/5196544

=====2013-2-14 更新=====
以前只是为了完成功能, 今天再看, 发现太多多余操作. 既然汇编都用了, 就效率至上吧
稍作优化:

static inline uint64_t get_cycle_count() {
#if defined(_IA32_)
    __asm__(
            "rdtscnt"
    );
#elif defined(_X86_64_)
    __asm__(
            "rdtscnt"
            "shlq $32, %raxnt"
            "movl %edx, %eaxnt"
            "rol $32,  %raxnt"
    );
#else
    union {
        uint64_t tick;
        struct {
            uint32_t low;
            uint32_t high;
        }st_t;
    }un_t;
    __asm__(
            "rdtscnt"
            "movl %%edx,%0nt"
            "movl %%eax,%1nt"
            :"=m"(un_t.st_t.high),"=m"(un_t.st_t.low)
            :
            :"%edx","%eax"
    );
    return un_t.tick;
#endif
}