【问题标题】:Measure time in Linux - time vs clock vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?在 Linux 中测量时间 - 时间 vs 时钟 vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?
【发布时间】:2012-09-05 17:10:26
【问题描述】:

在计时函数中,time、clockgetrusage、clock_gettime、gettimeofday和timespec_get,我想清楚地了解它们是如何实现的以及它们的返回值是什么以便知道在什么情况下我必须使用它们。

首先,我们需要将返回挂钟值的函数与返回进程或线程值的函数进行比较。 gettimeofday 返回挂钟值,clock_gettime 返回挂钟值或进程或线程值,具体取决于传递给它的Clock 参数。 getrusage 和 clock 返回进程值。

然后第二个问题是关于这些功能的实现以及它们的准确性。这些功能使用哪种硬件或软件机制。

似乎getrusage 仅使用内核刻度(通常为 1 毫秒长),因此不能比毫秒更准确。这样对吗? 那么getimeofday 函数似乎使用了可用的最准确的底层硬件。因此,在最近的硬件上,它的精度通常是微秒(由于 API 的原因不能更高)。 clock 怎么样,手册页谈到“近似”,这是什么意思? clock_gettime 呢,API 是纳秒级的,是不是意味着如果底层硬件允许就可以这么精确呢?单调性呢?

还有其他功能吗?

【问题讨论】:

    标签: c linux time linux-kernel


    【解决方案1】:

    问题在于 C 和 C++ 中有几个不同的时间函数可用,其中一些函数在不同实现之间的行为不同。还有很多半答案。编译时钟函数列表及其属性将正确回答这个问题。首先,让我们问一下我们正在寻找的相关属性是什么。看了你的帖子,我建议:

    • 时钟测量什么时间? (真实的、用户、系统,或者希望不是挂钟?)
    • 时钟的精度是多少? (秒、毫秒、微秒还是更快?)
    • 时钟绕回多少时间?或者有什么机制可以避免这种情况?
    • 时钟是单调的,还是会随着系统时间的变化而变化(通过 NTP、时区、夏令时、用户等)?
    • 上述内容在不同实现之间有何不同?
    • 具体功能是否过时、不规范等?

    在开始列表之前,我想指出,挂钟时间很少是正确使用的时间,但它会随着时区变化、夏令时变化或挂钟是否由 NTP 同步而变化.如果您使用时间来安排事件或对性能进行基准测试,那么这些都不是好事。它只顾名思义,墙上(或桌面)上的时钟。

    这是我目前在 Linux 和 OS X 中发现的时钟:

    • time() 从操作系统返回挂钟时间,精度以秒为单位。
    • clock() 似乎返回了用户和系统时间的总和。它存在于 C89 及更高版本中。曾经这应该是 CPU 时间周期,但现代标准like POSIX 要求 CLOCKS_PER_SEC 为 1000000,最大可能精度为 1 µs。我的系统上的精度确实是 1 µs。这个时钟一旦达到顶峰就会回绕(这通常发生在 ~2^32 个滴答声之后,这对于 1 MHz 时钟来说不是很长)。 man clock 表示从 glibc 2.18 开始,它在 Linux 中使用 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) 实现。
    • clock_gettime(CLOCK_MONOTONIC, ...) 提供纳秒级分辨率,是单调的。我相信“秒”和“纳秒”是分开存储的,每个都存储在 32 位计数器中。因此,任何回绕都会在数十年的正常运行时间之后发生。这看起来是一个非常好的时钟,但不幸的是它还没有在 OS X 上可用。POSIX 7 describes CLOCK_MONOTONIC as an optional extension。
    • getrusage() 原来是我的情况的最佳选择。它分别报告用户和系统时间并且不回绕。我的系统上的精度为 1 µs,但我也在 Linux 系统(带有 GCC 4.1.2 的 Red Hat 4.1.2-48)上进行了测试,精度仅为 1 ms。
    • gettimeofday() 以(名义上)微秒精度返回挂钟时间。在我的系统上,这个时钟似乎确实具有 µs 精度,但这不能保证,因为"the resolution of the system clock is hardware dependent"。 POSIX.1-2008 says that。 “应用程序应该使用clock_gettime() 函数而不是过时的gettimeofday() 函数”,所以你应该远离它。 Linux x86 并实现它as a system call。
    • mach_absolute_time() 是 OS X 上非常高分辨率 (ns) 计时的一个选项。在我的系统上,这确实提供了 ns 分辨率。原则上,这个时钟环绕,但是它使用 64 位无符号整数存储 ns,因此环绕在实践中不应该成为问题。便携性值得怀疑。
    • I wrote a hybrid function 基于 this snippet,在 Linux 上编译时使用 clock_gettime,在 OS X 上编译时使用 Mach 计时器,以便在 Linux 和 OS X 上获得 ns 精度。

    以上所有内容都存在于 Linux 和 OS X 中,除非另有说明。上面的“我的系统”是运行 OS X 10.8.3 和 MacPorts 的 GCC 4.7.2 的 Apple。

    最后,除了上面的链接之外,还有我认为有用的参考列表:


    更新:对于 OS X,clock_gettime 自 10.12 (Sierra) 起已实施。此外,基于 POSIX 和 BSD 的平台(如 OS X)共享 rusage.ru_utime 结构字段。

    【讨论】:

    • Mac OS X 没有clock_gettime,因此使用gettimeofday() 比clock_gettime() 更通用
    • 你没有提到times()(带有s),它自第1期以来就存在于POSIX中。关于GNU/Linux:根据时钟(3)手册页,clock()来自glibc 2.17 和更早的版本是在它之上实现的,但为了提高精度,它现在是在 clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...) 之上实现的,这也在 POSIX 中指定但是可选的。
    • @starflyer 时钟的精度部分受限于轮询时钟所需的时间。这是因为,如果我调用时钟并且返回需要 1 µs,那么从调用者的角度来看,时钟报告的时间将“关闭”1 µs。这意味着高精度时钟也必须是低延迟的。所以通常不会有你所说的权衡:最便宜的时钟也将是最准确的。
    • 大多数时钟也不关心夏令时/时区,即使它们被认为是挂钟。 time 和 gettimeofday 都返回,至少现在,自纪元以来的秒数(又名 unix-timestamps)。这与时区/夏令时无关。闰秒是另一回事......
    • 对于 Android 用户,使用 CLOCK_MONOTONIC 可能会出现问题,因为应用程序可能会与时钟一起暂停。为此,Android 添加了可通过 ioctl 访问的 ANDROID_ALARM_ELAPSED_REALTIME 计时器。关于这些和其他暂停相关信息的一些信息可以找到here
    【解决方案2】:

    C11 timespec_get

    用法示例:https://stackoverflow.com/a/36095407/895245

    返回的最大可能精度为纳秒,但实际精度由实现定义,可能更小。

    它返回挂墙时间,而不是 CPU 使用率。

    glibc 2.21 在sysdeps/posix/timespec_get.c 下实现它并直接转发到:

    clock_gettime (CLOCK_REALTIME, ts) < 0)
    

    clock_gettime 和 CLOCK_REALTIME 是 POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html,man clock_gettime 表示如果您在程序运行时更改某些系统时间设置,此度量可能会出现不连续性。

    C++11 计时码表

    既然说到了,那我们也来介绍一下吧:http://en.cppreference.com/w/cpp/chrono

    GCC 5.3.0(C++ 标准库在 GCC 源代码中):

    • high_resolution_clock 是 system_clock 的别名
    • system_clock 转发到以下可用的第一个:
      • clock_gettime(CLOCK_REALTIME, ...)
      • gettimeofday
      • time
    • steady_clock 转发到以下可用的第一个:
      • clock_gettime(CLOCK_MONOTONIC, ...)
      • system_clock

    提问于:Difference between std::system_clock and std::steady_clock?

    CLOCK_REALTIME 与 CLOCK_MONOTONIC: Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?

    【讨论】:

    • 很好的答案,揭开了典型实现的神秘面纱。这才是人们真正需要知道的。
    猜你喜欢
    • 2013-08-28
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-21
    • 2022-08-22
    • 1970-01-01
    • 2016-01-31
    • 1970-01-01
    相关资源
    最近更新 更多