首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >即使使用VDSO,clock_gettime也可能非常慢

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

Stack Overflow用户
提问于 2017-08-24 22:03:41
回答 2查看 2.9K关注 0票数 3

我在英特尔(R)至强(R) CPU E5-2667 v4 @3.20 CPU上使用CentOS Linux7.3.1611版

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

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

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

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

代码语言:javascript
复制
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);
}  

有没有人可以分享一些想法,哪里可能出了问题?

EN

回答 2

Stack Overflow用户

发布于 2017-08-24 23:10:06

让我们看一下clock_gettime的源代码

代码语言:javascript
复制
/* 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。当发生这种情况时,代码的运行速度会明显变慢。

票数 5
EN

Stack Overflow用户

发布于 2018-12-09 03:02:57

我不认为是clock_gettime调用本身的逻辑周期性地花费更长的时间,而是你的计时循环周期性地被中断,而这额外的时间表现为一个超长的间隔。

也就是说,任何类型的定时循环都容易被外部事件中断,例如中断。例如,除非使用非常具体的无计时内核配置(非默认配置),否则您的应用程序将被时钟中断周期性地中断,这将执行一些处理来查看是否应该运行另一个进程。即使最终没有其他进程运行,这也很容易导致几微秒的时间。

此外,硬件可能由于各种原因而临时暂停,例如当其他内核进入或离开空闲状态时发生的frequency transitions。我在8微秒左右测量了这些转换,接近您报告的值。在这些暂停期间,CPU不会执行指令,但TSC会继续运行,因此它显示为超长的时间间隔。

除此之外,还有一个ton of reasons可以解释为什么你会经历异常计时。这个答案还包括如果你感兴趣的话,你可以缩小可能的原因的方法。

最后,答案表明,当内核更新数据结构时,clock_gettime本身可能正在阻塞。虽然这当然是可能的,但我认为它的可能性比其他原因要小。您可以复制并粘贴VDSO代码,然后修改它以记录是否实际发生了阻塞,并调用它来查看您的暂停是否与阻塞相关。我想不会。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45863729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档