`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_clock
和 high_resolution_clock
与 boost::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
布局相比有几个优点:
有机会拥有更小的sizeof
。 system_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_clock
或system_clock
的类型别名。哪个,取决于平台。我的建议是使用steady_clock
或system_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_clock
或 system_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` 的比较的主要内容,如果未能解决你的问题,请参考以下文章