std::chrono

最近在做一些性能测试需要用到时间相关的工具,之前不管在哪几乎都用只gettimeofday,对时间工具相关真没怎么好好看一看,今天看了下std::chrono,发现c++真是想一统江湖啊,基本上想用的std::chrono都有了,抽象封装的挺合理,用起来也不麻烦,主要就三个概念:

具体就不解释了,官方文档说的很详细,这里自己写了一个简单的demo帮助理解这三个概念及用法,记录一下,这样以后在用的时候可以很快上手

代码如下:

#include <iostream>
#include <chrono>

int main() {
/*
 * 1. duration
 * 定义: std::chrono::duration<tick个数类型,tick精度> var(tick个数)
 */
  // 6 * (1 / 100) s
  std::chrono::duration<long long, std::ratio<1, 100>> hz100(6);
  // 6 * (1 / 100 / 100) s
  std::chrono::duration<double, std::ratio<1, 1>> second(hz100);
  // 6 * (1 / 100 / (100 / 60)) s
  std::chrono::duration<double, std::ratio<1, 60>> hz60(second);
  // 6 * (1 / 100 / (100 / 1000)) s
  std::chrono::duration<long long, std::ratio<1, 1000>> millisecond(hz100);
  std::cout << hz100.count() << " ticks" << std::endl;
  std::cout << second.count() << " ticks" << std::endl;
  std::cout << hz60.count() << " ticks" << std::endl;
  std::cout << millisecond.count() << " ticks" << std::endl;

/*
 * 2. time_point
 * 定义: std::chrono::time_point<时钟类型, std::chrono::duration> var(std::
 *         chrono::duration)
 */
  std::chrono::time_point<std::chrono::steady_clock,
    std::chrono::duration<long long, std::ratio<1, 1000000000>>> tp_at_3ns(
        std::chrono::duration<long long, std::ratio<1, 1000000000>>(3));
  
  std::chrono::time_point<std::chrono::steady_clock,
    std::chrono::duration<long long, std::ratio<1, 1000000000>>> tp_at_1us(
        std::chrono::duration<long long, std::ratio<1, 1000000>>(1));
  //对两个time_point求差,低精度自动转为高精度
  std::chrono::duration<long long, std::ratio<1, 1000000000>> diff =
    tp_at_1us - tp_at_3ns;
  std::cout << "diff = " << diff.count() << " ns" << std::endl;

/*
 * 3. steady_clock
 *
 * std::chrono::steady_clock::now()返回的是:
 *   std::chrono::time_point<std::chrono::steady_clock,
 *     std::chrono::duration<long long, std::ratio<1, 1000000000>>>
 * 这个也是std::chrono::time_point的默认值(ns), 所以一般直接写成如下即可
 */
  std::chrono::steady_clock::time_point begin =
    std::chrono::steady_clock::now();

  int i = 0;
  while (i < 20000) {
    i++;
  }
  std::chrono::steady_clock::time_point end =
    std::chrono::steady_clock::now();

  std::chrono::duration<long long, std::ratio<1, 1000000000>> diff_in_ns =
    end - begin;
  std::cout << "used: " << diff_in_ns.count() << " ns" << std::endl;
    /*
     * 不能进行从高精度往低精度的转换, 以下三种编译不通过
     * std::chrono::duration<long long, std::ratio<1, 1000000>> diff_in_us =
     *   end - begin;
     * std::chrono::duration<long long, std::ratio<1, 1000>> diff_in_ms =
     *   end - begin;
     * std::chrono::duration<long long, std::ratio<1, 1>> diff_in_s =
     *   end - begin;
     *
     * 如果一定要转, 可以使用std::duration_cast<std::chrono::duration>, 如下:
     */
    std::chrono::duration<long long, std::ratio<1, 1000000>> diff_in_us =
      std::chrono::duration_cast<std::chrono::duration<long long,
      std::ratio<1, 1000000>>>(end - begin);

    std::cout << "loop 20k times used: " << diff_in_us.count() << " us"
      << std::endl;

/*
 * system_clock
 */
  std::chrono::system_clock::time_point today =
    std::chrono::system_clock::now();

  std::chrono::duration<int,std::ratio<60*60*24, 1> > one_day(1);
  std::chrono::duration<int,std::ratio<1, 1> > one_second(1);

  std::chrono::system_clock::time_point today_plus_1s = today + one_second;
  std::chrono::system_clock::time_point tomorrow = today + one_day;

  std::time_t tt;
  tt = std::chrono::system_clock::to_time_t(today);
  std::cout << "today is " << ctime(&tt);

  tt = std::chrono::system_clock::to_time_t(today_plus_1s);
  std::cout << "today plus one second is " << ctime(&tt);

  tt = std::chrono::system_clock::to_time_t(tomorrow);
  std::cout << "tomorrow plus one second is " << ctime(&tt);
  return 0;
}

输出如下:

6 ticks
0.06 ticks
3.6 ticks
60 ticks
diff = 997 ns
used: 50629 ns
loop 20k times used: 50 us
today is Sat Jan  7 22:35:50 2017
today plus one second is Sat Jan  7 22:35:51 2017
tomorrow plus one second is Sun Jan  8 22:35:50 2017

总结

说来惭愧,在c++17的今天,我还依旧停留在c++98,虽然用什么标准说是不重要(比如leveldb),不过我至今都没好好用c++11的原因并不是因为我能站在上帝视角客观公正说出c++98比c++11好并且是在深思熟虑之后继续选择守旧,而是一个字:懒。。。因为真正用起来新标准有很多东西和用法要学,麻烦。不过这些东西的确有它方便强大的地方,至少目前std::thread、std::atomic、std::chrono我就觉得很爽,以后要加快学习,争取早日全面用上c++11(我知道如果c++17党看到这话会笑掉牙,哇哈哈)。

理论、编码、语言工具,三手都要抓,三手都要硬,啊哈哈哈哈哈哈(好吧,这篇博客不正经)