前言 - std::chrono 的用法

三种主要类型

  • clocks: 包括一个起始点(epoch)以及一个变动率(tick rate)
  • time point: 自特定 clock 的 epoch 之后经过的 duration
  • duration: 指时间跨度,包括衡量跨度的时间单位以及有多少个单位(count of ticks)

关于 clock 的用法

  1. steady_clocksystem_clock的区别:

    • 前者绝对单调,不可调整;后者基于真实系统时钟,不一定单调;
    • 前者更适合测量 time interval;后者是唯一可以转换为 c-style time(std::time_t)的 clock 类型;
  2. 使用 clock 记录时间点以及函数执行用时
    不同的时钟类型都拥有一个函数now()来指示当前的时刻

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 使用std::chrono库记录函数执行用时
#include <chrono>
#include <iostream>

using namespace std::chrono;

int fib(int n){ // this is banned in real life!!!
if(n <= 1) return 1;
return fib(n-1) + fib(n-2);
}

int main(int argc, char *argv[])
{
auto beforeTime = steady_clock::now();
auto ans = fib(43);
auto afterTime = steady_clock::now();
duration<double, std::ratio<1>> spendTime = afterTime - beforeTime;
std::cout << "It costs " << spendTime.count() << " seconds to calculate fib(43)" << std::endl;
std::cout << "The result is " << ans << std::endl;
return 0;
}

muduo 网络库的时间戳系统的核心就是一个整形数据,表示自 epoch 以来流逝的微妙数。我对其做了一点改进,使用std::chrono::time_point来支撑时间戳系统,原因也很简单,更好用。std::chronoduration可以很方便的在各个时间单位之间进行转换,比如seconds, milliseconds, hours等等。

不过需要注意的是,将time_point转换为以年月日时分秒这样的格式化时刻,还是需要借助 C 语言的time_tstruct tm来进行转换。所幸std::chrono::system_clock中有可以直接将time_point转换为time_t的函数,倒也不算麻烦。

另外,我将整个时间戳系统写成了模板的形式,可以选择不同的clockduration类型。当然,默认情况下就使用system_clocksystem_clock::duration

这里列出时间戳系统的格式化输出的核心函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::string toFormattedString(bool showMicroseconds = true) const {
// YYYY-MM-DD hh:mm:ss:micross
char buf[64] = {0};
auto microSecondsSinceEpoch = duration_cast<microseconds>(stamp_.time_since_epoch()).count();
auto tt = system_clock::to_time_t(stamp_); // so this means that timestamp should use system_clock as ClockType
auto tm_ = localtime(&tt);
if(showMicroseconds){
snprintf(buf, sizeof buf, "%4d-%02d-%02d %02d:%02d:%02d:%06ld",
tm_->tm_year+1900, tm_->tm_mon+1, tm_->tm_mday,
tm_->tm_hour, tm_->tm_min, tm_->tm_sec,
microSecondsSinceEpoch % kMicroSecondsPerSecond);
} else {
snprintf(buf, sizeof buf, "%4d-%02d-%02d %02d:%02d:%02d",
tm_->tm_year+1900, tm_->tm_mon+1, tm_->tm_mday,
tm_->tm_hour, tm_->tm_min, tm_->tm_sec);
}
return buf;
}

全部源码详见duduo 网络库