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

xam8gpfp  于 2023-03-28  发布在  Linux
关注(0)|答案(2)|浏览(133)

在定时函数timeclockgetrusageclock_gettimegettimeofdaytimespec_get中,我想清楚地了解它们是如何实现的,以及它们的返回值是什么,以便知道在什么情况下必须使用它们。
首先,我们需要对返回挂钟值的函数进行分类,并与返回进程或线程值的函数进行比较。gettimeofday返回挂钟值,clock_gettime返回挂钟值进程或线程值,具体取决于传递给它的Clock参数。getrusageclock返回进程值。
然后第二个问题是关于这些功能的实现以及它们的准确性。这些功能使用哪种硬件或软件机制。
getrusage似乎只使用内核标记(通常1ms长),因此不能比ms更精确。对吗?然后gettimeofday函数似乎使用了最精确的底层硬件。因此,其精度通常为微秒(不能更多,因为API)在最近的硬件上。clock怎么样,手册页谈到“近似”,它是什么意思?clock_gettime怎么样,API是纳秒,这是否意味着如果底层硬件允许的话,它能够如此准确?单调性呢?
还有其他功能吗?

at0kjp5o

at0kjp5o1#

问题是在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 with 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并将其实现为系统调用。
  • mach_absolute_time()是OS X上非常高分辨率(ns)计时的一个选项。在我的系统上,这确实给予ns分辨率。原则上这个时钟是环绕的,但是它使用64位无符号整数存储ns,所以环绕在实践中应该不是问题。可移植性是有问题的。
  • 我编写了一个基于this snippet的混合函数,在Linux上编译时使用clock_gettime,在OS X上编译时使用Mach计时器,以便在Linux和OS X上都获得ns精度。

上面的所有内容都存在于Linux和OS X中,除非另有说明。上面的“我的系统”是运行Mac Ports的OS X 10.8.3和GCC 4.7.2的Apple。
最后,除了上面的链接外,这里还有一个参考文献列表,我发现这些参考文献很有帮助:

fnvucqvd

fnvucqvd2#

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 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_REALTIMECLOCK_MONOTONICDifference between CLOCK_REALTIME and CLOCK_MONOTONIC?

相关问题