【问题标题】:Do CLOCK_MONOTONIC and CLOCK_MONOTONIC_COARSE have the same base?CLOCK_MONOTONIC 和 CLOCK_MONOTONIC_COARSE 是否具有相同的基础?
【发布时间】:2020-01-31 00:58:57
【问题描述】:

clock_gettime() 的手册页将 CLOCK_MONOTONIC_COARSE 描述为:

CLOCK_MONOTONIC 的更快但不太精确的版本。在您需要非常快的时候使用,但是 不是细粒度的时间戳。

一个人成为另一个人的“版本”是什么意思?

假设我将 CLOCK_MONOTONIC 值截断到与粗略值相同的精度,我能否有效地比较两者?

【问题讨论】:

  • 通俗地说,“版本”是指被引用的函数属于可以获取时间的函数类。
  • 如果可以避免的话,我建议不要使用 CLOCK_MONOTONIC_COARSE。正如您所发现的,文档不清楚。我一直在研究 Linux 计时代码,我不相信 MONOTONIC 和 MONOTONIC_COARSE 之间不再有区别。但是如果你真的很在意这种区别,你就不能相信文档,你要么必须检查内核计时代码(这是不可理解的),要么找 Linux 内核计时专家来询问。
  • @Steve Summit:我不同意你的观点,但“这取决于”。我在下面更新了我的答案,添加了这个链接:access.redhat.com/documentation/en-US/Red_Hat_Enterprise_MRG/…
  • @AShelly - 我认为我们已经确定了您考虑使用 CLOCK_MONOTONIC_COARSE 而不是 CLOCK_MONOTONIC 的唯一原因是可能如果您的应用程序正在生成许多性能优势,频繁的“时间”系统调用。 “不太精确”只是意味着“不太准确”。如果这就是您的意思,则不存在“截断”或“舍入”的问题。问:这(连同其他回复/讨论)是否回答了您的问题?如果没有,问:您能否提供一个“用例”来帮助我们更好地理解您的问题?
  • @AShelly:你的问题解决了吗?如果不是,您能否进一步解释一下您不确定的内容(例如,一个用例)?

标签: c linux clock


【解决方案1】:

这里是列出 Posix/Linux 时钟不同“版本”的手册页:

https://linux.die.net/man/2/clock_gettime

足够新的 glibc 版本和 Linux 内核支持 以下时钟:

  • CLOCK_REALTIME

    测量真实(即挂钟)时间的系统范围的时钟。 设置此时钟需要适当的权限。这个时钟是 受系统时间不连续跳跃的影响(例如,如果 系统管理员手动更改时钟),并由 由 adjtime(3) 和 NTP 执行的增量调整。

  • CLOCK_REALTIME_COARSE(从 Linux 2.6.32 开始;特定于 Linux)

    更快但不太精确的 CLOCK_REALTIME 版本。当你使用 需要非常快但不是细粒度的时间戳。

  • CLOCK_MONOTONIC

    无法设置的时钟,表示单调时间,因为某些 未指定的起点。该时钟不受 系统时间的不连续跳跃(例如,如果系统 管理员手动更改时钟),但受 由 adjtime(3) 和 NTP 执行的增量调整。

  • CLOCK_MONOTONIC_COARSE(自 Linux 2.6.32 起;特定于 Linux)

    CLOCK_MONOTONIC 的更快但不太精确的版本。当你使用 需要非常快但不是细粒度的时间戳。

  • CLOCK_MONOTONIC_RAW(从 Linux 2.6.28 开始;特定于 Linux) 与 CLOCK_MONOTONIC 类似,但提供对不受 NTP 调整或 adjtime(3) 执行的增量调整。

  • CLOCK_BOOTTIME(从 Linux 2.6.39 开始;特定于 Linux) 与 CLOCK_MONOTONIC 相同,除了它还包括系统暂停的任何时间。这允许应用程序获得 暂停感知单调时钟,而无需处理 CLOCK_REALTIME 的并发症,如果 使用 settimeofday(2) 更改时间。

  • CLOCK_PROCESS_CPUTIME_ID 来自 CPU 的高分辨率每进程计时器。

  • CLOCK_THREAD_CPUTIME_ID 线程特定的 CPU 时间时钟。

正如您在上面看到的,CLOCK_MONOTONIC_COARSE 是在 Linux 2.6.32 中引入的。以下是理由(以及具体的源补丁):

https://lwn.net/Articles/347811/

在与一些想要非常快但又不想要的应用程序编写者交谈之后 细粒度的时间戳,我决定尝试实现一个新的clock_ids 到 clock_gettime(): CLOCK_REALTIME_COARSE 和 CLOCK_MONOTONIC_COARSE 它返回最后一次滴答的时间。这非常快,因为我们没有 必须访问任何硬件(如果您正在使用这可能会非常痛苦 像 acpi_pm 时钟源),我们甚至可以使用 vdso clock_gettime() 方法来避免系统调用。唯一的权衡是你 只能获得低分辨率刻度时间分辨率。

这不是一个新想法,我知道 Ingo 在 -rt 树中有一个补丁 使 vsyscall gettimeofday() 返回粗粒度时间 vsyscall64 sysctrl 设置为 2。但这会影响所有应用程序 在系统上。

使用此方法,应用程序可以选择适当的速度/粒度 为自己取舍。

谢谢 -约翰

附录:

问:使用 CLOCK_MONOTONIC_COARSECLOCK_REALTIME_COARSE 可能会使哪些用例受益?

A:在 Linux 2.6.32 时间框架(2010-2011)中,“...应用程序工作负载(尤其是数据库和金融服务应用程序)执行极其频繁的 gettimeofday 或类似的时间函数调用”:

Redhat Enterprise: 2.6. gettimeofday speedup

许多应用程序工作负载(尤其是数据库和金融服务 应用程序)执行极其频繁的 gettimeofday 或类似时间 函数调用。优化此调用的效率可以提供 主要好处。

【讨论】:

  • 这很详细,但并没有真正回答我可以比较两个不同时钟基准的值的问题。
  • 那么,“比较”到底是什么意思?具体而言,您会如何“比较”?他们会“相似”吗:是的。它们会非常相似吗?大概。我应该使用哪一个?这完全取决于您的用例;)根据史蒂夫·萨米特的观察,它可能不会有太大的不同......“希望能有所帮助......
【解决方案2】:

CLOCK_MONOTONIC_COARSE 使用与 CLOCK_MONOTONIC 相同的时基(但与 CLOCK_MONOTONIC_RAW 相比,特别不使用)。具体来说,它们都使用wall_to_monotonic 来转换从 tk 的 xtime 派生的值。 RAW 使用完全不同的时间源。

请记住,CLOCK_MONOTONIC_COARSE 每次滴答仅更新一次(因此通常约为 1 毫秒,但请询问 clock_getres() 以确保)。如果这个精度足够好,那么一定要减去你的时钟值。

【讨论】:

    【解决方案3】:

    简短的回答是YES(至少对于 Linux!),您可以比较它们、计算延迟等...

    精度将是不太精确的,很可能是粗略的。

    看这个简短的节目:

    #include <time.h>
    #include <stdio.h>
    
    int main()
    {
        int ret;
        struct  timespec res;
    
        ret = clock_getres(CLOCK_MONOTONIC, &res);
        if (0 != ret)
            return ret;
        printf("CLOCK_MONOTONIC resolution is: %ld sec, %ld nsec\n", (long)res.tv_sec, (long)res.tv_nsec);
    
        ret = clock_getres(CLOCK_MONOTONIC_COARSE, &res);
        if (0 != ret)
            return ret;
        printf("CLOCK_MONOTONIC_COARSE resolution is: %ld sec, %ld nsec\n", (long)res.tv_sec, (long)res.tv_nsec);
    
        return 0;
    }
    

    它返回(Ubuntu 20.04 - 64 位 - 内核 5.4)

    CLOCK_MONOTONIC resolution is: 0 sec, 1 nsec
    CLOCK_MONOTONIC_COARSE resolution is: 0 sec, 4000000 nsec
    

    所以 MONOTONIC 具有纳秒精度,而 COARSE 具有 4 毫秒精度。

    与上面的评论不同,我相反建议在您需要的时间允许时使用 COARSE 版本。

    在用户程序中对时钟的调用非常频繁,以至于它们在 vDSO 中占有一席之地

    当您使用 COARSE 版本时,您的系统调用完全为零,并且它的速度与您的机器可以运行几条指令一样快。感谢 vDSO,您的程序在与 COARSE 通话期间完全停留在“用户空间”中。 使用其他类型的时钟,您将有一些系统调用和对硬件的潜在访问权限。所以至少切换到“内核”并返回到“用户空间”。

    如果您的程序只需要十几次调用,这当然是零重要性,但如果相反,如果程序严重依赖时钟,它可以节省大量时间。这就是为什么 vDSO 存在的首要原因:性能!

    • 首先定义计时所需的精度。是 秒够了,你需要毫秒、微秒等...
    • 请记住,除非您正在修补 RT 系统,否则时间是 相对价值!想象一下你调用了clock_gettime,然后立即 返回后,您的线程会因任何内核业务而中断: 你得到的准确度是多少?这正是著名的问题 2001 年击败 HAL:太空漫游:“现在几点了?”。
    • 从中您可以得出您需要的时钟类型。
    • 您可以混合使用 MONOTONIC 和它的 COARSE 版本,但仍然可以计算延迟或进行比较(这是最初的问题)。但当然,精确度是不那么精确的。
    • 单调最适合进行时间延迟和比较,因为它们不依赖于实时时间(如您的手表显示的那样)。当用户更改实际时间时,它们不会更改。
    • 相反,如果您需要显示事件发生的时间(对用户有意义),请不要使用单调

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-09
      • 1970-01-01
      • 2016-02-22
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 2020-08-07
      相关资源
      最近更新 更多