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


148

其中计时功能,timeclock getrusageclock_gettimegettimeofdaytimespec_get,我想清楚地了解它们是如何实现的,为了知道在什么情况下我必须使用他们什么是他们的返回值。

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

然后,第二个问题涉及这些功能的实现以及结果的准确性。这些功能使用哪种硬件或软件机制。

似乎getrusage只使用了内核滴答(通常为1ms长),结果比ms更加准确。这样对吗?然后,该getimeofday功能似乎使用了最准确的基础硬件。结果,它的精度通常是最新硬件上的微秒(由于API而不能更高)。关于什么的clock,关于“逼近”该名男子页讲,这是什么意思?怎么回事clock_gettime,API只需十亿分之一秒,这是否意味着如果基础硬件允许的话,它就能如此精确?单调性如何?

还有其他功能吗?

Answers:


198

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

  • 时钟是几点钟?(真实的,用户的,系统的,或者希望不是壁钟?)
  • 时钟的精度是多少?(秒,毫秒,微秒还是更快?)
  • 时钟多少钟后回绕?还是有某种机制可以避免这种情况?
  • 时钟是单调的,还是会随系统时间的变化而变化(通过NTP,时区,夏令时,由用户等)?
  • 上面的实现之间有何不同?
  • 特定功能是否过时,不标准等?

在开始列出之前,我想指出壁钟时间很少是正确的使用时间,但是它会随着时区的变化,夏令时的变化或壁钟是由NTP同步而变化的。如果您花时间安排事件或基准性能,那么这些事情都不是一件好事。顾名思义,这真的非常有用,因为它可以挂在墙上(或台式机)上。

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

  • time() 从操作系统返回挂钟时间,以秒为单位。
  • clock()似乎返回用户和系统时间的总和。它存在于C89及更高版本中。一次应该以周期为单位的CPU时间,但是像POSIX这样的现代标准要求CLOCKS_PER_SEC为1000000,最大可能精度为1 µs。我的系统上的精度确实为1 µs。该时钟在达到顶峰时就会回绕(通常发生在〜2 ^ 32个滴答之后,对于1 MHz的时钟来说不是很长)。man clock说自glibc 2.18起,它是clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)在Linux中实现的。
  • clock_gettime(CLOCK_MONOTONIC, ...)提供纳秒分辨率,是单调的。我相信“秒”和“纳秒”分别存储在32位计数器中。因此,经过数十年的正常运行时间后,任何折回都将发生。这看起来像一个很好的时钟,但是不幸的是,它在OS X上尚不可用。POSIX 7 描述CLOCK_MONOTONIC为可选扩展
  • getrusage()事实证明,这是我的最佳选择。它分别报告用户时间和系统时间,并且不会回绕。我的系统上的精度为1 µs,但我也在Linux系统(带GCC 4.1.2的Red Hat 4.1.2-48)上进行了测试,精度仅为1 ms。
  • 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中。上面的“我的系统”是一台运行Mac X且带有GCC 4.7.2的OS X 10.8.3的Apple。

最后,除了上面的链接之外,这是我认为有帮助的参考文献列表:


更新clock_gettime从10.12(Sierra)开始已实现OSX 。同样,基于POSIX和BSD的平台(如OS X)都共享rusage.ru_utimestruct字段。


Mac OS X没有clock_gettime,因此使用的gettimeofday()功能比clock_gettime()
bobobobo

1
您还没有提到times()(带有s),它从问题1开始就存在于POSIX中。关于GNU / Linux:根据clock(3)手册页,clock()glibc 2.17和更早的版本是在它的基础上实现的,但需要改进现在clock_gettime(CLOCK_PROCESS_CPUTIME_ID,...),它已在POSIX中指定,但是是可选的。
vinc17 2014年

2
@starflyer时钟的精度部分受限于轮询时钟所花费的时间。这是因为,如果我调用时钟,并且需要1 µs的时间返回,那么从调用者的角度来看,时钟报告的时间将“关闭” 1 µs。这意味着高精度时钟也必须是低延迟的。因此,通常情况下,您不会在此权衡取舍:最便宜的时钟也会最精确。
Douglas B. Staple 2015年

3
同样,即使被视为壁钟,大多数时钟也不关心夏时制/时区。二者timegettimeofday返回,至少时下,秒因为历元(又名UNIX的时间戳)。这与时区/夏令时无关。seconds秒是另一个故事……
Zulan

2
对于Android用户,使用CLOCK_MONOTONIC可能会出现问题,因为该应用可能会随着时间的推移而被挂起。为此,Android添加了可通过ioctl访问的ANDROID_ALARM_ELAPSED_REALTIME计时器。关于这些和其他暂停相关的信息可以发现一些信息在这里
伊泰·比安科

17

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 ++ stdlib在GCC源代码中):

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

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

CLOCK_REALTIMEvs CLOCK_MONOTONICCLOCK_REALTIME和CLOCK_MONOTONIC之间的区别?


1
很好的答案使典型的实现变得神秘。那是人们真正需要知道的。
Celess
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.