在Linux中测量时间 - 时间与时钟对比getrusage vs clock_gettime vs gettimeofday vs timespec_get?

时间:2012-09-12 16:05:49

标签: c linux time linux-kernel

在时间函数timeclock getrusageclock_gettimegettimeofdaytimespec_get中,我想清楚地了解它们是怎样的实现了它们的返回值是什么,以便知道在哪种情况下我必须使用它们。

首先,我们需要将返回挂钟值的函数与返回进程或线程值的函数进行分类。 gettimeofday会返回挂钟值,clock_gettime会返回挂钟值进程或线程值,具体取决于传递给它的Clock参数。 getrusageclock会返回流程值。

然后第二个问题涉及这些功能的实施,因此,它们的准确性。这些功能使用哪种硬件或软件机制。

似乎getrusage仅使用内核tick(通常为1ms长),因此不能比ms更精确。这样对吗? 然后getimeofday函数似乎使用最准确的底层硬件。因此,它的准确性通常是近期硬件上的微秒(因为API而不能更多)。 怎么样clock,手册页谈到“近似”,它是什么意思? 那么clock_gettime,API是纳秒级,是否意味着如果底层硬件允许它,它能够如此准确?单调性怎么样?

还有其他功能吗?

2 个答案:

答案 0 :(得分:180)

问题在于C和C ++中有几种不同的时间函数,其中一些在实现之间的行为有所不同。周围还有很多半答案。编译时钟函数列表及其属性将正确回答问题。对于开始,让我们问一下我们正在寻找的相关属性。看看你的帖子,我建议:

  • 时钟衡量的是什么时间? (真实的,用户的,系统的,或者,希望不是,挂钟?)
  • 时钟的精度是多少? (s,ms,μs,还是更快?)
  • 时钟绕了多长时间?或者有一些机制可以避免这种情况吗?
  • 时钟是单调的,还是会随着系统时间的变化而变化(通过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系统(Red Hat 4.1.2-48,GCC 4.1.2)上进行了测试,精度仅为1 ms。
  • gettimeofday()以(标称)μs精度返回挂钟时间。在我的系统上,这个时钟似乎具有μ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中。上面的“我的系统”是Apple运行的OS X 10.8.3,MacPorts的GCC 4.7.2。

最后,除了上面的链接之外,这里有一个我发现有用的参考文献列表:


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

答案 1 :(得分:14)

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.htmlman 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

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

CLOCK_REALTIME vs CLOCK_MONOTONICDifference between CLOCK_REALTIME and CLOCK_MONOTONIC?