用于记录时间戳的不同 C++ 时钟的优缺点是什么?

What are the pros & cons of the different C++ clocks for logging time stamps?

打印我的日志时,我希望每条消息都有一个时间戳,测量自程序启动以来的时间。最好以纳秒为单位,尽管毫秒也可以:

(  110 ns) Some log line 
( 1220 ns) Another log line 
( 2431 ns) Now for some computation...
(10357 ns) Error!

据我了解,C++ chrono 库中有三种不同的时钟和另外两种 C 风格的时钟:

上述任务各自的优缺点是什么?

system_clock 是一个与 UTC(不包括闰秒)保持时间的时钟。每隔一段时间(可能一天几次),它会进行少量调整,以使其与正确的时间保持一致。这通常通过 NTP 等网络服务来完成。这些调整通常以微秒为单位,但时间可以向前或向后。这个时钟的时间戳实际上有可能(虽然不太可能也不常见)向后移动一点点。除非被管理员滥用,否则 system_clock 不会按总量跳跃,例如由于夏令时或更改计算机的本地时区,因为它始终跟踪 UTC。

steady_clock 就像一个秒表。它与任何时间标准都没有关系。它一直在滴答作响。它可能不会保持完美的时间(没有时钟确实如此)。但它永远不会调整,尤其是不会倒退。它非常适合计时短代码位。但由于它从未得到调整,它可能会随着时间的推移相对于 system_clock 进行漂移,而 system_clock 已调整为与 UTC 保持同步。

这归结为 steady_clock 最适合短时计时。它通常还具有纳秒分辨率,但这不是必需的。 system_clock 最适合计时“长”时间,其中“长”非常模糊。但可以肯定的是,数小时或数天符合“长”的条件,而低于一秒的持续时间则不算。如果您需要将时间戳与人类可读时间相关联,例如民用日历上的 date/time,那么 system_clock 是唯一的选择。

high_resolution_clock 被允许作为 steady_clocksystem_clock 的类型别名,实际上总是如此。但一些平台别名为 steady_clock,有些平台别名为 system_clock。所以恕我直言,最好直接选择 steady_clocksystem_clock 这样你就知道你得到了什么。

虽然没有指定,但 std::time 通常限制为一秒的分辨率。所以对于需要亚秒级精度的情况是完全不能用的。否则 std::time 跟踪 UTC(不包括闰秒),就像 system_clock.

std::clock 跟踪处理器时间,而不是物理时间。也就是说,当您的线程不忙于做某事并且 OS 已将其停放时,std::clock 的测量值将不会反映该停机期间增加的时间。如果这是您需要衡量的,这将非常有用。如果您在使用它时没有意识到您正在测量的是处理器时间,那可能会非常令人惊讶。

C++20 的新增功能

C++20 向 <chrono> 库添加了四个时钟:

utc_clocksystem_clock 类似,只是它计算的是闰秒。当您需要在闰秒插入点上减去两个 time_point 并且您绝对需要计算插入的闰秒(或其分数)时,这主要有用。

tai_clock 测量自 1958-01-01 00:00:00 以来的秒数,并且在该日期比 UTC 提前 10 秒。它没有闰秒,但每次在 UTC 中插入一个闰秒,TAI 和 UTC 的日历表示又相差一秒。

gps_clock 模拟 GPS 时间系统。它测量自 1980 年 1 月的第一个星期日 00:00:00 UTC 以来的秒数。与 TAI 一样,每次在 UTC 中插入一个闰秒,GPS 和 UTC 的日历表示就会相差另一秒。由于 GPS 和 TAI 处理 UTC 闰秒的方式相似,因此 GPS 的日历表示总是比 TAI 落后 19 秒。

file_clockfilesystem 库使用的时钟,也是产生别名为 std::filesystem::file_time_typechrono::time_point 的时钟。

可以使用 C++20 中名为 clock_cast 的新命名转换在 system_clockutc_clock、[=34= 的 time_point 之间进行转换]、gps_clockfile_clock。例如:

auto tp = clock_cast<system_clock>(last_write_time("some_path/some_file.xxx"));

tp 的类型是基于 system_clocktime_point,与 file_time_type 具有相同的 duration 类型(精度)。