我正在玩高精度计时器,我的第一个测试之一是使用rdtsc来测量printf.下面是我的测试程序,然后输出.我注意到的是,第一次printf运行时,它在第一次打印时总是比在后续打印时长约25倍.这是为什么?
#include <stdio.h>
#include <stdint.h>
// Sample code grabbed from wikipedia
__inline__ uint64_t rdtsc(void)
{
uint32_t lo, hi;
__asm__ __volatile__ (
"xorl %%eax,%%eax \n cpuid"
::: "%rax", "%rbx", "%rcx", "%rdx");
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return (uint64_t)hi << 32 | lo;
}
int main(int argc, const char *argv[])
{
unsigned int i;
uint64_t counter[10];
uint64_t sum = 0;
for (i = 0; i < 10; i++)
{
counter[i] = rdtsc();
printf("Hello, world\n");
counter[i] = rdtsc() - counter[i];
}
for (i = 0; i < 10; i++)
{
printf("counter[%d] = %lld\n", i, counter[i]);
sum += counter[i];
}
printf("avg = %lld\n", sum/10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并输出:
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world
counter[0] = 108165
counter[1] = 6375
counter[2] = 4388
counter[3] = 4388
counter[4] = 4380
counter[5] = 4545
counter[6] = 4215
counter[7] = 4290
counter[8] = 4237
counter[9] = 4320
avg = 14930
Run Code Online (Sandbox Code Playgroud)
(作为参考,这是在OSX上使用gcc编译的)
我的猜测是,在第一次调用的printf,标准输出资源没有在缓存中,呼叫将需要把它纳入缓存 - 因此它的速度较慢.对于所有后续调用,缓存已经很热.
第二种可能的解释是,如果这是在Linux上(也可能适用于OSX,我不确定),程序需要设置流方向.(ASCII与UNICODE)这是在第一次调用使用该流的函数时完成的,并且在流关闭之前是静态的.我不知道设置这个方向的开销是多少,但这是一次性成本.
如果有人认为我完全错了,请随时纠正我.