在Linux中测量时间 – 时间vs时钟vs getrusage vs clock_gettime vs gettimeofday vs timespec_get?

在时间函数中, time getrusageclock_gettimegettimeofdaytimespec_get ,我想要清楚地知道它们是如何实现的以及它们的返回值是什么,以便知道在哪种情况下我必须使用它们。

首先,我们需要对返回挂钟值的函数进行分类,并与返回进程或线程值的函数进行比较。 gettimeofday返回挂钟值, clock_gettime根据传递给它的Clock参数返回挂钟值进程或线程值。 getrusageclock返回过程值。

那么第二个问题就是关于这些function的实现以及它们的准确性。 这些function使用哪种硬件或软件机制。

似乎getrusage只使用内核tick(通常为1ms长),因此不能比ms更准确。 这样对吗? 那么getimeofday函数似乎使用了最精确的底层硬件。 因此,在最近的硬件上,其准确度通常是微秒(不能因为API而更多)。 关于clock ,手册页讲的是“逼近”,这是什么意思? 那么clock_gettime ,这个API在纳秒级,这是否意味着如果底层硬件允许的话它可以非常精确? 单调性呢?

还有其他的function吗?

问题是在C和C ++中有几个不同的时间函数,其中一些在实现之间有不同的行为。 还有很多的答案在四处stream动。 编译时钟函数列表及其属性将正确回答问题。 对于开始,我们来问一下我们正在寻找的相关属性。 看着你的post,我build议:

  • 什么时间测量时钟? (真实的,用户的,系统的,还是希望不是挂钟?)
  • 时钟的精度是多less? (s,ms,μs还是更快?)
  • 时钟回绕了多less时间? 还是有一些机制可以避免这种情况?
  • 时钟是单调的,还是会随着系统时间的变化而改变(通过NTP,时区,夏时制,用户等)?
  • 以上各项如何变化?
  • 具体的function是否过时,不标准等?

在开始列表之前,我想指出的是,挂钟时间几乎不是正确的使用时间,而是随着时区的变化,夏时制的变化或挂钟是否被NTP同步而改变。 如果您使用时间安排活动或基准testing,这些事情都不是很好。 这只是真正的名字所说,在墙上(或桌面)的时钟。

以下是我在Linux和OS X中发现的时钟:

  • time()从OS返回挂钟时间,精确度以秒为单位。
  • clock()似乎返回用户和系统时间的总和。 它出现在C89以后。 有一段时间应该是CPU周期的时间,但像POSIX这样的现代标准要求CLOCKS_PER_SEC为1000000,最大精度为1μs。 我的系统精度确实是1μs。 这个时钟一旦回到顶部(这通常发生在〜2 ^ 32个刻度之后,对于1MHz的时钟来说不是很长)。 man clock说,自glibc 2.18以来,它是在Linux中用clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)的。
  • clock_gettime(CLOCK_MONOTONIC, ...)提供纳秒分辨率,是单调的。 我相信“秒”和“纳秒”分别存储在32位计数器中。 因此,经过十几年的正常运行后,任何环绕都会发生。 这看起来像是一个非常好的时钟,但不幸的是它在OS X上还不可用CLOCK_MONOTONIC 7 将CLOCK_MONOTONIC描述为可选的扩展 。
  • getrusage()原来是我的情况的最佳select。 它分别报告用户和系统时间,不会环绕。 我的系统精度为1微秒,但我也在Linux系统上testing过(Red Hat 4.1.2-48和GCC 4.1.2),精度只有1毫秒。
  • gettimeofday()以(名义上)μs的精度返回挂钟时间。 在我的系统上,这个时钟确实有μs精度,但是这并不能保证,因为“系统时钟的分辨率是依赖于硬件的” 。 POSIX.1-2008 说 。 “应用程序应该使用clock_gettime()函数而不是过时的gettimeofday()函数”,所以你应该远离它。 Linux x86并将其作为系统调用来实现 。
  • mach_absolute_time()是OS X上非常高分辨率(ns)时序的一个选项。在我的系统中,这确实给出了ns分辨率。 原则上这个时钟环绕,但是它使用一个64位的无符号整数来存储ns,所以实际上这个环绕不应该是一个问题。 可移植性是值得怀疑的。
  • 我写了一个基于这个片段 的混合函数 ,它在Linux上编译时使用clock_gettime,或者在OS X上编译时使用Mach计时器,以便在Linux和OS X上获得ns精度。

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

最后,这里是我发现除了以上链接之外还有帮助的参考文献列表:


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

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_gettimeCLOCK_REALTIME是POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html,man man clock_gettime表示如果在程序运行时更改一些系统时间设置,则此度量可能会有不连续性。

C ++ 11 chrono

既然我们在这,也让我们来介绍一下: http : //en.cppreference.com/w/cpp/chrono

GCC 5.3.0(C ++ stdlib在GCC源代码中):

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

问: 在std :: system_clock和std :: steady_clock之间的区别?

CLOCK_REALTIMECLOCK_MONOTONIC : CLOCK_REALTIME和CLOCK_MONOTONIC之间的区别?