`std::chrono` 时钟与`boost::xtime` 的比较

Posted

技术标签:

【中文标题】`std::chrono` 时钟与`boost::xtime` 的比较【英文标题】:Comparison of `std::chrono` clocks with `boost::xtime` 【发布时间】:2019-02-13 21:01:44 【问题描述】:

C++11 std::chrono 时钟 steady_clockhigh_resolution_clockboost::xtime::xtime_get() 在各种平台上的怪癖和一般属性相比如何?

标准不保证high_resolution_clock 是稳定的(它明确提到它可能是system_clock 的别名),所以这是一个需要注意的陷阱。我想到的其他属性:

分辨率:C++11 标准似乎不保证任何分辨率;这些时钟的“现实”分辨率是多少? boost::xtime_get() 在相同系统上的表现如何?

最长持续时间:我知道,例如clock() 在具有 32 位 clock_t 和 1 MHz 标称时钟分辨率的系统上大约一个小时后崩溃。 (是的,我知道clock() 应该做一些不同的工作。)C++11 标准时钟能否在所有已知平台上处理数天甚至数周的持续时间?

任何其他已知问题或令人惊讶的怪癖(编辑:std::chrono 时钟或boost::xtime::xtime_get

【问题讨论】:

嗯,一个明显的比较是其中一个是标准的,而另一个不是。 如果您担心high_resolution_clock 的稳定性,如果它在平台上稳定,is_steady 成员将是true 这可以写一篇不错的文章,但是这里的答案太宽泛了 @FrançoisAndrieux 更新了问题;我没有给出任何关于 boost 怪癖的例子的原因是我目前什么都不知道。 如果我知道这样的文章我可以总结要点并写一个答案,但是只发布一个链接不被认为是一个正确的答案,无论如何我不;) 【参考方案1】:

C++11 std::chrono 时钟 stable_clock 和 high_resolution_clock 与 boost::xtime::xtime_get() 在各种平台上的怪癖和一般属性相比如何?

任何时序库都只能提供底层操作系统/硬件组合可以提供的功能——句号。

即使库 API 承诺提供纳秒级分辨率,但这并不意味着底层操作系统/硬件可以提供这种精度。所以最终时序API并不能提高平台的质量。

boost::xtime 基本上被 C(以及随后的 C++)标准化为 timespec。这是一个second, nanosecond 对,既可用作时间点,也可用作持续时间,具体取决于它在标准C 头文件中使用的函数。尽管对 boost headers 的快速调查似乎仅将xtime 用作时间点(我可能错过了一些东西)。

timespec 已有很长的使用历史,尤其是在 POSIX 系统中。它在 POSIX 系统上的存在时间比 std::chrono 长得多,std::chrono 于 2008 年设计,并在 C++11 (2011) 中标准化。

timespec (xtime) 的范围通常大于宇宙的年龄。虽然在无法提供 64 位整数类型的系统上,timespec 的范围会明显更小:+/-68 年,当它用作时间点时,通常以 1970 年左右为中心。

如上所述,timespec 所有平台上宣传纳秒精度,但只会提供底层平台可以提供的精度。

chrono 为时间点和持续时间提供单独 类型。这有助于在编译时捕获错误。例如,如果将两个时间点相加,则无法编译。今天早上 9 点 + 今天早上 7 点是荒谬的。但是,如果您减去两个时间点,那将非常有意义并返回一个单独的类型:持续时间。今天早上 9 点 - 今天早上 7 点是 2 小时。

chrono 为持续时间和时间点提供多种类型,这些类型在精度和表示上可能不同。 “内置”持续时间是纳秒、微秒、毫秒、秒、分钟和小时,每个都用有符号整数类型表示(该列表在 C++20 规范中扩展)。但是您可以使用自己的精度和表示形式(例如浮点数或安全整数库)创建自己的持续时间类型。

任何给定平台的chrono 的实现者都可以宣传平台“now()”函数的精度。 IE。它不必总是纳秒,它可能是微秒或其他单位。供应商不需要诚实,但他们通常是。客户端可以在编译时以编程方式查询 now() 的返回类型的精度(毕竟这是 C++)。

chrono 数据结构是 count of units,而不是 xtime seconds, nanoseconds 数据结构。对于chrono,持续时间和时间点都是如此,即使它们是不同的类型。

count of units 布局与seconds, nanoseconds 布局相比有几个优点:

有机会拥有更小的sizeofsystem_clock::time_point 通常为 64 位,而xtime 通常为 128 位。这确实为xtime 提供了优越的范围。然而,chrono 库也可以用于 128 位整数类型,其范围随后将比 xtime 的范围更大。

客户端可以使用chrono 来权衡大小/范围。 xtime 客户得到他们所得到的。

使用count 数据结构比使用seconds, nanoseconds 进行算术编程更快/更高效且更容易。这导致代码更小、更快且通常更无错误(seconds, nanoseconds 表示的负值是一个持续的恐怖故事)。

对于给定的sizeof 和精度,使用count 数据结构总是可以获得比seconds, nanoseconds 等多字段数据结构更大的范围。

该标准不保证 high_resolution_clock 是稳定的(它明确提到它可能是 system_clock 的别名),所以这是一个需要注意的陷阱。

实际上high_resolution_clock 始终是steady_clocksystem_clock 的类型别名。哪个,取决于平台。我的建议是使用steady_clocksystem_clock,这样你就知道你在处理什么了。

分辨率:C++11 标准似乎不保证任何分辨率;这些时钟的“现实”分辨率是多少?

广告解决方案是:

libc++/llvm:

system_clock
    rep is long long : 64 bits
    period is 1/1,000,000
    is_steady is 0

high_resolution_clock
    rep is long long : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

steady_clock
    rep is long long : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock is the same type as steady_clock

libstdc++/gcc:

system_clock
    rep is long : 64 bits
    period is 1/1,000,000,000
    is_steady is 0

high_resolution_clock
    rep is long : 64 bits
    period is 1/1,000,000,000
    is_steady is 0

steady_clock
    rep is long : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock is the same type as system_clock

VS-2013:

system_clock
    rep is __int64 : 64 bits
    period is 1/10,000,000
    is_steady is 0

high_resolution_clock
    rep is __int64 : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

steady_clock
    rep is __int64 : 64 bits
    period is 1/1,000,000,000
    is_steady is 1

high_resolution_clock is the same type as steady_clock

由于我的开场白,“现实生活中的”解决方案很可能与任何给定平台的xtime 相同。

在所有已知平台上,C++11 标准时钟能否处理数天甚至数周的持续时间?

是的。甚至几个月甚至几年。

您将遇到的第一个持续时间限制是在处理纳秒级分辨率时。 chrono 保证这将具有至少 64 位有符号整数表示,为您提供 +-292 年的范围。当谈到system_clock时,这个范围将以1970年为中心。

任何其他已知问题或令人惊讶的怪癖

在或接近范围限制时,chrono 库可以轻松且无声地溢出。例如,如果您将microseconds::max()nanoseconds::max() 进行比较,您将遇到溢出并得到不确定的结果。发生这种情况是因为比较运算符会先将 microseconds 转换为 nanoseconds,然后再进行比较,并且该转换会溢出。

避开持续时间和时间点范围限制。如果您必须处理它们,并且不确定如何处理,请查看 *** 以获取答案。如果搜索不满意,请针对您的问题提出具体问题。

【讨论】:

哇,感谢您提供详细的答案。 - 因此,如果我需要以毫秒级的精度测量一段代码的已用挂钟时间,但代码有时可能会运行数周甚至更长时间,那么出于所有实际目的std::chrono::steady_clock 将是我的符合标准的便携式朋友? steady_clock 是毫秒级计时的不错选择。但是对于大约几周的时间安排不太好。但这并不可怕。 steady_clock 通常会计算您平台的硬件时钟周期计数器,并将其转换为方便的单位,例如纳秒。但是没有完美的时钟这样的东西,而且您的计算机时钟处于平均水平较差的一侧。您的石英腕表通常每周会松动一两秒。您计算机的时钟不会做得更好,而且可能会更差。 system_clock 会不时询问网络上的其他时钟现在是什么时间并自行纠正。因此,在毫秒级的短时间间隔上会更糟糕,但在几周级的长间隔上会更好。 steady_clocksystem_clock 都可以。但每个人都有自己的长处和短处。【参考方案2】:

测试sleep_for 行为的一些第一手和第二手结果,持续时间为 1 毫秒:

以下平台倾向于“睡过头”,至少平均而言(超过 1000 次迭代):

适用于 Linux / g++ 的 Windows 子系统(1.8 毫秒,显然是开销) 正版 Ubuntu/g++(1.1 毫秒) FreeBSD/clang(1.1 毫秒) Wingwin / g++(16 毫秒,显然是最小值) OS X (Darwin) / g++ / POSIX 线程模型 (1.2 ms)

到目前为止,似乎没有任何平台平均“睡眠不足”。

【讨论】:

以上是关于`std::chrono` 时钟与`boost::xtime` 的比较的主要内容,如果未能解决你的问题,请参考以下文章

std chrono 时间同步

C++ 11 时间编程 std::chrono::steady_clock使用--计算程序执行时间

C++11 std::chrono库详解

std::chrono 和 cout

如何使用 std::chrono 库设置特定时间?

无法解析带有 NDK r10e 的 std::chrono