深刻理解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
相關文章
相關標籤/搜索