在计时函数timeclockgetrusageclock_gettimegettimeofdaytimespec_get中,我想清楚地了解它们是如何实现的,以及它们的返回值是什么,以便知道我必须在哪种情况下使用它们.

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

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

似乎getrusage只使用内核刻度(通常为1ms长),因此不可能比ms更精确.是对的吗? 则getimeofday函数似乎使用可用的最精确的底层硬件.因此,在最近的硬件上,它的精度通常是微秒级(由于API的原因不能更高). 手册页上提到的"近似"clock是怎么回事,它是什么意思? 那么clock_gettime呢,API的单位是纳秒,这是否意味着如果底层硬件允许的话,它就可以如此精确呢?单调性呢?

还有其他功能吗?

推荐答案

问题是在C和C++中有几个不同的时间函数,其中一些在不同的实现中行为不同.也有很多半途而废的答案在四处流传.编译时钟函数及其属性的列表可以正确地回答这个问题.作为开始,让我们来问一下我们正在寻找的相关属性是什么.看了你的帖子,我建议:

  • 这个钟量几点?(真实的、用户的、系统的,或者,希望不是挂钟?)
  • 这个钟的精度是多少?(s、ms、µs或更快?)
  • 过了多长时间钟才会转?还是有某种机制可以避免这种情况?
  • 时钟是单调的,还是会随着系统时间的变化(通过NTP、时区、夏令时、用户等)而改变?
  • 以上内容在不同的实现中有什么不同?
  • 具体功能是否过时、不标准等.?

在开始列出之前,我想指出,挂钟时间很少是正确的使用时间,而它会随着时区的变化、夏令时的变化或挂钟是否由NTP同步而变化.如果您使用时间来安排事件或对性能进行基准测试,那么这些都不是好事情.它只对名字说的有好处,墙上(或桌面上)的钟.

以下是我到目前为止在Linux和OSX中发现的时钟:

  • time()返回操作系统中的挂钟时间,精度以秒为单位.
  • clock()似乎返回用户和系统时间之和.它存在于C89及更高版本中.有一段时间,这应该是以周期为单位的CPU时间,但现代标准like POSIX要求时钟每秒clock()0000次,最大可能的精度为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位计数器中.因此,任何总结都会在几十年的正常运行时间之后发生.这看起来是一个非常好的时钟,但不幸的是它还不能在OSX.POSIX7describes CLOCK_MONOTONIC as an optional extension上使用.
  • 事实证明,getrusage()英镑是适合我这种情况的最佳 Select .它会分别报告用户和系统时间,而不会进行总结.我的系统的精度是1µs,但我也在Linux系统(Red Hat 4.1.2-48和GCC 4.1.2)上进行了测试,精度只有1ms.
  • gettimeofday()以(标称)µs精度返回挂钟时间.在我的系统上,这个时钟似乎确实有µs精度,但这不能保证,因为"the resolution of the system clock is hardware dependent".POSIX.1-2008 says that."应用程序应该使用clock_gettime()函数,而不是过时的gettimeofday()函数",所以您应该远离它.Linuxx86并实现它as a system call.
  • 在OSX上,mach_absolute_time()是一个非常高分辨率(Ns)计时的选项.在我的系统上,这确实提供了ns的分辨率.原则上,这个时钟回绕,但是它使用64位无符号整数存储n,所以实际上回绕应该不是问题.可移植性是有问题的.
  • I wrote a hybrid function基于this snippet,在Linux上编译时使用lock_gettime,或在OS X上编译时使用Mach计时器,以便在Linux和OS X上都获得ns精度.

以上所有功能都存在于Linux和OSX中,除非另有说明.上图中的"我的系统"是一台运行OSX10.8.3的苹果电脑,搭载MacPorts的GCC 4.7.2操作系统.

最后,除了上面的链接之外,我还发现了一些有用的参考资料:


Update:对于OS X,从10.12(Sierra)起已经实现了clock_gettime.此外,基于POSIX和BSD的平台(如OS X)都共享rusage.ru_utime struct字段.

C++相关问答推荐

C中的整字母后缀i是什么

由于未签名int导致的运行时错误"

使用SWI—Prolog的qsave_program生成二进制文件有什么好处?'

常数函数指针优化

找出文件是否包含给定的文件签名

无法用C++编译我的单元测试

ESP32在vTaskDelay上崩溃

Char变量如何在不使用方括号或花括号的情况下存储字符串,以及它如何迭代到下一个字符?

轮询libusb_pollfd struct 列表的正确方式是什么?

在C++中访问双指针

如何使解释器存储变量

为什么双精度d=flt_max+flt_max;在c语言中得到inf的结果

在C中创建任意类型的只读指针参数

错误...的多个定义(&Q)首先在这里定义&

对于STM32微控制器,全局偏移表.get和.Got.plt必须为零初始化

具有正确标头的C struct 定义问题

为什么会导致分段故障?(C语言中的一个程序,统计文件中某个单词的出现次数)

计算SIZE_MAX元素的长数组的大小

在printf()中用%.*S格式填充长度为0的字符串是否会调用任何UB?如果是,是哪一个?

创建 makefile 来编译位于不同目录中的多个源文件