C++11中的std::chrono时钟steady_clock和high_resolution_clock在各个平台上的特性和一般属性与boost::xtime::xtime_get()相比如何?
任何计时库都只能提供底层操作系统/硬件组合可以提供的内容,没有例外。即使库API承诺纳秒级分辨率,这也并不意味着底层操作系统/硬件可以提供该精度。因此,最终的计时API无法改善平台的质量。
boost::xtime基本上是由C标准化(随后是C ++)的timespec。这是一个{秒,纳秒}对,根据它在标准C头文件中使用的函数不同,既用作时间点,又用作时间持续时间。尽管快速调查boost头文件似乎仅将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规范中扩展)。但是,您可以创建自己的持续时间类型,具有自己的精度和表示形式(例如,浮点或安全int库)。
实现任何给定平台的
chrono
实现者都可以宣传平台"
now()
"函数的精度。即,它不必总是纳秒,可以是微秒或其他单位。厂商没有义务诚实,但他们通常会这样做。客户端可以在编译时以编程方式查询
now()
的返回类型及其精度(毕竟这是C++)。
chrono
数据结构是
{单位计数}
,而不是
xtime
{秒、纳秒}
数据结构。对于
chrono
,即使这些是不同的类型,这也适用于持续时间和时间点。
{单位计数}
布局相比
{秒、纳秒}
布局具有几个优点:
- 有机会拥有更小的
sizeof
。 system_clock::time_point
通常为64位,而xtime
通常为128位。这确实使xtime
具有卓越的范围。但是,chrono
库还可以与128位积分类型一起使用,随后将具有比xtime
更大的范围。
- 客户端可以通过
chrono
进行大小/范围权衡。 xtime
客户端将得到他们的内容。
- 使用
{计数}
数据结构进行算术运算更快、更高效,编程也更容易,而使用{秒、纳秒}
则会导致代码更小、更快,并且通常更少出现错误(使用{秒、纳秒}
表示负值是一个长期的恐怖故事)。
- 对于给定的
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
由于我开场白的原因,"现实生活"中的解决方案很可能与任何给定平台上的相同。
C++11标准时钟是否能在所有已知平台上处理以天、甚至是周为单位的持续时间?
可以。即使是月份和年份也可以。
你会遇到的第一个持续时间限制是处理纳秒分辨率时。chrono保证它将具有至少64位有符号整数表示,使您拥有+-292年的范围。当涉及system_clock时,该范围将以1970年为中心。
还有其他已知的问题或令人惊讶的怪癖吗?
当操作接近或超过范围限制时,chrono库很容易且无声地溢出。例如,如果将microseconds::max()与nanoseconds::max()进行比较,则会发生溢出并获得不确定的结果。这是因为比较运算符将在执行比较之前先将微秒转换为纳秒,并且该转换会导致溢出。
尽量避开持续时间和time_point范围限制。如果不得不处理它们,并且不确定如何处理,请在Stackoverflow上寻找答案。如果搜索结果不令人满意,请提出特定于您关注的问题。
high_resolution_clock
的稳定性,它有一个is_steady
成员,如果在该平台上是稳定的,则为true
。 - François Andrieux