为什么在循环中使用 gettimeofday,第二个 diff 与其他 diff 如此不同?

Why the 2nd diff is so different from the others, using gettimeofday in a loop?

这个功能对我来说比较陌生,所以写了个小程序来熟悉一下。 这是我的程序(只是在多次调用 gettimeofday 之间打印圈数)。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>

typedef struct timeval t_timeval;

t_timeval    get_diff(t_timeval prev)
{
    t_timeval current_time;
    gettimeofday(&current_time, NULL);
    printf("diff : %ld seconds and %ld micro seconds\n",
        current_time.tv_sec - prev.tv_sec, current_time.tv_usec - prev.tv_usec);
    return (current_time);
}

int        get_time_laps()
{
    int            i = 0;
    t_timeval    prev;

    gettimeofday(&prev, NULL);
    while (i++ < 50)
        prev = get_diff(prev);
    return (0);
}

int        main()
{
    get_time_laps();
    return (0);
}

结果是:

diff : 0 seconds and 0 microseconds
diff : 0 seconds and 47 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 2 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 1 microseconds
diff : 0 seconds and 0 microseconds
[...]
diff : 0 seconds and 1 microseconds

所以我想知道为什么第二个差异与其他差异如此不同。仅供参考,我做了几次测试,每次我都得到这个模式。

发生这种情况的原因很有趣。由于 gettimeofday 会使用一个经常被调用的系统调用,linux 使用一个调用 vdso 的东西,它会自动映射到您的程序中,以便访问与时间信息相关的东西,而不需要系统调用(因为系统调用成本高昂)。

其工作方式是当您调用 gettimeofday 时,您的程序将在 vdso 中查找符号。当它找到它时,我会将它缓存在内存中以便更快地访问。这就是为什么第一次通话较慢的原因。你可以找到更好的解释方法here

Oftentimes the C library will do detection with the first call and then cache the result for subsequent calls.

还有一个很好的方法来对 vdso 与实际系统调用进行基准测试 here