为什么第一个printf需要更长的时间?

Ale*_*lex 3 c printf rdtsc

我正在玩高精度计时器,我的第一个测试之一是使用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编译的)

Mys*_*ial 5

我的猜测是,在第一次调用的printf,标准输出资源没有在缓存中,呼叫将需要把它纳入缓存 - 因此它的速度较慢.对于所有后续调用,缓存已经很热.

第二种可能的解释是,如果这是在Linux上(也可能适用于OSX,我不确定),程序需要设置流方向.(ASCII与UNICODE)这是在第一次调用使用该流的函数时完成的,并且在流关闭之前是静态的.我不知道设置这个方向的开销是多少,但这是一次性成本.

如果有人认为我完全错了,请随时纠正我.


Oli*_*rth 5

也许是第一次,代码printf不在指令缓存中,因此必须从主内存加载.在后续运行中,它已经在缓存中.