深刻理解std::chrono的时钟Clock

std::chrono是C++11引入的日期时间处理库,其中包含3种时钟:system_clock,steady_clock,high_resolution_clock。近来须要使用高精度时间,很天然想到使用high_resolution_clock,然而使用后发现并不是预期的获得自1970/1/1零点以后的计数,而是一个小得多的数字。那么这三种时钟有什么区别,用在什么状况下,咱们来一探究竟。this

问题

auto tp = std::chrono::high_resolution_clock::now();
std::cout << tp.time_since_epoch().count() << std::endl;

上述代码输出一个比较小的数字,high_resolution_clock的精度是纳秒,不多是这么小的数字。code

三种时钟的区别

所谓时钟,是指从一个时点开始,按照某个刻度的一个计数。以下代码摘自VC2017。orm

  • system_clock
struct system_clock
{   // wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime
typedef long long rep;
typedef ratio_multiply<ratio<_XTIME_NSECS_PER_TICK, 1>, nano> period;
typedef chrono::duration<rep, period> duration;
typedef chrono::time_point<system_clock> time_point;
static constexpr bool is_steady = false;

对于system_clock,其起点是epoch,即1970-01-01 00:00:00 UTC,其刻度是1个tick,也就是_XTIME_NSECS_PER_TICK纳秒。ip

  • high_resolution_clock
typedef steady_clock high_resolution_clock;

high_resolution_clock实际上和steady_clock同样。ci

  • steady_clock
struct steady_clock
{   // wraps QueryPerformanceCounter
typedef long long rep;
typedef nano period;
typedef nanoseconds duration;
typedef chrono::time_point<steady_clock> time_point;
static constexpr bool is_steady = true;

steady_clock的刻度是1纳秒,起点并不是1970-01-01 00:00:00 UTC,通常是系统启动时间,这就是问题的关键。steady_clock的做用是为了获得不随系统时间修改而变化的时间间隔,因此凡是想获得绝对时点的用法都是错误的。steady_clock是没有to_time_t()的实现的,而system_clock是有的。io

三种时钟用在何时

  • system_clock:用在须要获得绝对时点的场景
auto tp = std::chrono::system_clock::now();
std::time_t tt = std::chrono::system_clock::to_time_t(tp);
std::cout << tt << "seconds from 1970-01-01 00:00:00 UTC" << std::endl;
  • steady_clock:用在须要获得时间间隔,而且这个时间间隔不会由于修改系统时间而受影响的场景
auto tp1 = std::chrono::steady_clock::now();
//do something
auto tp2 = std::chrono::steady_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::microseconds>(tp2 - tp1).count() << "microseconds" << std::endl;
  • high_resolution_clock:high_resolution_clock是system_clock或steady_clock之一,根据状况使用

常见的错误用法

  • std::this_thread::sleep_until传入的是steady_clock::time_point
  • 根据steady_clock::time_point获得time_t
相关文章
相关标签/搜索