linux - 即使使用 VDSO,clock_gettime 也可能非常慢

标签 linux time-measurement vdso

我在 Intel(R) Xeon(R) CPU E5-2667 v4 @ 3.20GHz 上使用 CentOS Linux 7.3.1611

在我的用户空间应用程序测试期间,我注意到 clock_gettime(CLOCK_MONOTONIC, &ts) 可能需要 5-6 微秒而不是平均约 23 纳秒。它可能每 10000 个后续调用只发生一次,但它可能会发生。

如果没有VDSO库,就可以解释了。然而,VDSO用于每个clock_gettime(我通过strace检查过)。

不管相应的线程是否关联到某个CPU核心。不管这个 CPU 内核是否与操作系统隔离。这意味着测试应用程序可能会在专用 CPU 内核上运行,但无论如何都可能出现延迟!

我通过比较两个后续 clock_gettime 调用的结果来测量延迟,例如:

unsigned long long __gettimeLatencyNs() {
    struct timespec t1_ts;
    struct timespec t2_ts;
    clock_gettime(CLOCK_MONOTONIC, &t1_ts);
    clock_gettime(CLOCK_MONOTONIC, &t2_ts);
    return ((t2_ts.tv_sec - t1_ts.tv_sec)*NANO_SECONDS_IN_SEC + t2_ts.tv_nsec - t1_ts.tv_nsec);
}  

谁能分享一些想法,那里可能有什么问题?

最佳答案

让我们看一下 clock_gettime 的源代码:

/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
notrace static int __always_inline do_realtime(struct timespec *ts)
{
    unsigned long seq;
    u64 ns;
    int mode;

    do {
        seq = gtod_read_begin(gtod);
        mode = gtod->vclock_mode;
        ts->tv_sec = gtod->wall_time_sec;
        ns = gtod->wall_time_snsec;
        ns += vgetsns(&mode);
        ns >>= gtod->shift;
    } while (unlikely(gtod_read_retry(gtod, seq)));

    ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
    ts->tv_nsec = ns;

    return mode;
}

我们在这里看到的是代码在循环内运行。此循环使用 unlikely 条件进行注释。该条件与以下事实有关:此代码读取有时会更新的共享内存,并且在更新时,代码需要等待更新完成。

那么,您的问题最有可能的答案是,您经常会在相应的内核代码更新其结构时捕获到 clock_gettime。发生这种情况时,代码运行速度会明显变慢。

关于linux - 即使使用 VDSO,clock_gettime 也可能非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45863729/

相关文章:

linux - glibc 中的getpid 工作程序是什么?

c - sys_readlink 失败 EFAULT - 备选方案

c - 缓冲区溢出: send exploit with pwntools changes bytes

c - C程序的时间测量为0

java - 在Java中以微秒分辨率测量时间的最有效、 "cheap"和最准确的方法是什么?

linux-kernel - 在strace中捕获vDSO

linux - gettimeofday 系统调用如何工作?

mysql - 找不到符号 mysql_select_db@libmysqlclient_16 的版本节点

c - 用于 linux c 的图形用户界面

android - 在 Android 上测量耗时(重启)