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

Man*_*lva 137 c linux time linux-kernel

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

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

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

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

还有其他功能吗?

Dou*_*ple 185

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

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

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


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

  • 此外,大多数时钟都不关心夏令时/时区,即使它们被认为是*挂钟*.'time`和`gettimeofday`两者都回归,至少在今天,自纪元以来的几秒钟(又名unix-timestamps).这与时区/夏令时无关.闰秒是另一个故事...... (3认同)
  • @starflyer时钟的精度部分受限于轮询时钟所需的时间.这是因为,如果我调用时钟并返回需要1μs,那么从调用者的角度来看,时钟报告的时间将"关闭"1μs.这意味着高精度时钟也必须具有低延迟.因此,通常你不会谈论你所讨论的权衡:最便宜的时钟也将是最准确的. (2认同)
  • 对于Android用户,使用CLOCK_MONOTONIC可能会有问题,因为应用程序可能会随时钟一起被暂停.为此,Android添加了可通过ioctl访问的ANDROID_ALARM_ELAPSED_REALTIME计时器.关于这些和其他暂停相关信息的一些信息可以在[这里]找到(http://lwn.net/Articles/429925/) (2认同)

Cir*_*四事件 15

C11 timespec_get

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

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

它返回挂起时间,而不是CPU使用率.

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

clock_gettime (CLOCK_REALTIME, ts) < 0)
Run Code Online (Sandbox Code Playgroud)

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

C++ 11 chrono

既然我们在这里,我们也要介绍它们: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_MONOTONIC:CLOCK_REALTIME和CLOCK_MONOTONIC之间的区别?