linux时间测试,在Linux中测量时间-时间vs时钟vs getrusage vs clock_gettime

42701053d1fb5f3a19610fbb53a3421e.png

犯罪嫌疑人X

问题是在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。最后,除了上面的链接之外,这是我发现有用的参考文献列表:http://blog.habets.pp.se/2010/09/gettimeofday-should-never-be-used-to-measure-time如何在Linux下测量C程序的实际执行时间?http://digitalsandwich.com/archives/27-benchmarking-misconceptions-microtime-vs-getrusage.htmlhttp://www.unix.com/hp-ux/38937-getrusage.html更新:自OS clock_gettime10.10(Sierra)起已实现。同样,基于POSIX和BSD的平台(如OS X)都共享rusage.ru_utimestruct字段。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`clock_gettime` 函数的函数体实现是由操作系统提供的,具体实现可能因操作系统而异。以下是一种可能的实现方式: ```C #include <time.h> #include <errno.h> #include <sys/time.h> #include <sys/resource.h> int clock_gettime(clockid_t clk_id, struct timespec *tp) { int ret = 0; struct timeval tv; struct timezone tz; if (clk_id != CLOCK_REALTIME && clk_id != CLOCK_MONOTONIC && clk_id != CLOCK_PROCESS_CPUTIME_ID && clk_id != CLOCK_THREAD_CPUTIME_ID) { errno = EINVAL; return -1; } if (tp == NULL) { errno = EFAULT; return -1; } if (clk_id == CLOCK_REALTIME) { ret = gettimeofday(&tv, &tz); tp->tv_sec = tv.tv_sec; tp->tv_nsec = tv.tv_usec * 1000; } else if (clk_id == CLOCK_MONOTONIC) { ret = clock_gettime(CLOCK_MONOTONIC_RAW, tp); } else if (clk_id == CLOCK_PROCESS_CPUTIME_ID) { ret = getrusage(RUSAGE_SELF, &ru); tp->tv_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; tp->tv_nsec = ru.ru_utime.tv_usec * 1000 + ru.ru_stime.tv_usec * 1000; } else if (clk_id == CLOCK_THREAD_CPUTIME_ID) { ret = getrusage(RUSAGE_THREAD, &ru); tp->tv_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; tp->tv_nsec = ru.ru_utime.tv_usec * 1000 + ru.ru_stime.tv_usec * 1000; } if (ret == -1) { errno = EINVAL; return -1; } return 0; } ``` 这个实现,函数首先检查 `clk_id` 是否是支持的时钟类型,以及 `tp` 是否为 `NULL`。然后,根据不同的时钟类型调用不同的系统函数获取时间值,并将结果存储到 `timespec` 结构体。最后,返回 `0` 表示成功,或者返回 `-1` 表示失败并设置 `errno` 错误码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值