Loading

C++ 计时类

C++中的chrono

开篇

C中有<time.h>,而在C++中使用<chrono>来表示时间

学习chrono之前,应该掌握两个单词:duration(时间间隔),time_point(时间点)。先从一个小例子开始讲起

#include<iostream>
#include<chrono>
#include<thread>
int main()
{
    using namespace std::literals::chrono_literals;
    auto start = std::chrono::high_resolution_clock::now();		//获取当前时间
    std::this_thread::sleep_for(2s);					//此线程休眠2s
    auto end = std::chrono::high_resolution_clock::now();		//获取当前时间
    std::chrono::duration<float> duration = end - start;		//计算时间间隔
    std::cout << duration.count() << "s\n";				//2.00008s
}

以上,将end以及start两个time_point相减,得到duration,最后将duration的数值打印输出

duration 时间间隔

由下图可以看出std::chrono::xx实际上是一个别名。说人话就是规定了d = 2000ms

别名 实际类型(以下省略名称空间std::chrono)
std::chrono::nanoseconds duration<long long, std::ratio<1, 1000000000>>
std::chrono::microseconds duration<long long, std::ratio<1, 1000000>>
std::chrono::milliseconds duration<long long, std::ratio<1, 1000>>
std::chrono::seconds duration<long long>
std::chrono::minutes duration<int, std::ratio<60>>
std::chrono::hours duration<int, std::ratio<3600>>

熟悉using的朋友应该清楚下面两行代码是等效的

auto d1 = std::chrono::seconds(2);
auto d2 = std::chrono::duration<long long>(2);		//代表了2s的时间间隔

关于duration这个模板类,它有两个模板参数

template<typename Rep, typename Period = std::ratio<1>>
class duration;

Rep代表时间间隔的类型,可以是doublefloatintlong long等等。

Period代表周期,它的类型std::ratio也是一个模板类,它两个非类型模板参数,其中std::intmax_tlong long的别名

//typedef long long intmax_t;
template<std::intmax_t Num, std::intmax_t Denom = 1>
class ratio;

ratio可以理解为一个分数,Num代表分子,Denom代表分母,例如std::ratio<1, 20>代表$\frac{1}{20}$

durationratio的第二个模板参数都有默认值,以下方代码为例:时间间隔的类型为int,周期为$\frac{1}{1000}$,表示的时间就是$100*\frac{1}{1000}=0.1$,单位是秒,也就是100ms

auto mstime = std::chrono::duration<int, std::ratio<1, 1000>>(100);		//100ms

再来个例子,$30*\frac{60}{1}=1800$,单位是秒,也就是30min

auto mintime = std::chrono::duration<int, std::ratio<60>>(30);			//30min

总的来说我认为std::ratioduration类中的运用可以理解成是单位,比方说std::ratio<3600>代表的就是小时(一小时有3600秒)

扯了那么久回归正题,以下代码让本线程休眠2s

auto d1 = std::chrono::seconds(2);
auto d2 = std::chrono::duration<int>(2);
std::this_thread::sleep_for(d1);		//d1和d2都是代表2s,但d1相对来说可读性更高

还有另外一种方法,就是开篇中所给出的。选择哪种方式就见仁见智了

using namespace std::literals::chrono_literals;
std::this_thread::sleep_for(2s);	    //2s
//std::this_thread::sleep_for(2min);        //2min

time_point 时间点

在开篇的例子中,我使用了auto来让编译器自行推断类型

auto start = std::chrono::high_resolution_clock::now();		//获取当前时间
//std::chrono::time_point<std::chrono::steady_clock> start;	//start是这种类型

std::chrono::time_point无非就是时间点,它的模板参数接收一个“clock”

std::chrono::high_resolution_clock 是一个很神奇的东西,它是一个别名。而且它实际是什么东西取决于库和配置。在VS中它指的就是std::chrono::steady_clock

using std::chrono::high_resolution_clock = std::chrono::steady_clock;	//MSVC中
using std::chrono::high_resolution_clock = std::chrono::system_clock;	//gcc的libstdc++中

这就是为什么auto推断出来的startstd::chrono::time_point<std::chrono::steady_clock>类型

根据常识,两个时间点相减的结果是一段时间间隔,所以开篇的例子是这么写的

std::chrono::duration<float> duration = end - start;		//计算时间间隔

然后再使用duration.count()得到具体的时间

chrono的一个小应用

设计一个计时类,在开始计时时创建出该类的一个实例,跳出作用域后调用析构函数,在控制台输出从创建到销毁所花费的时间。可以用于比较各种算法,各种拷贝等所耗费的时间

#include<chrono>
#include<iostream>
class inTime
{
    std::chrono::time_point<std::chrono::steady_clock> start, end;
    std::chrono::duration<float, std::ratio<1, 1000>> val;		//float精度的以毫秒为单位的时间间隔
public:
    inTime() {
        start = std::chrono::high_resolution_clock::now();
    }
    ~inTime() {
        end = std::chrono::high_resolution_clock::now();
        val = end - start;
        std::cout << val.count() << "ms" << std::endl;
    }
};
int main()
{
    {
        inTime it;
        Quick_Sort(vec);		//伪代码,调用一个算法,传入一个vector作为参数
    }
    //计数类离开作用域,在控制台输出所经历的时间
}

计时类的优化

class inTime
{
private:
    std::chrono::high_resolution_clock::time_point start;
public:
    inTime() : start(std::chrono::high_resolution_clock::now()) {}
    ~inTime()
    {
        Stop();
    }
    void Stop()
    {
        auto end = std::chrono::high_resolution_clock::now();
        auto _startValue = std::chrono::time_point_cast<std::chrono::microseconds>(start).
            time_since_epoch().count();
        auto _endValue = std::chrono::time_point_cast<std::chrono::microseconds>(end).
            time_since_epoch().count();			//转换成微秒,long long类型
        auto duration = _endValue - _startValue;
        std::cout << duration << "us\n";
    }
};

杂谈(待更)

众所周知,Debug调试模式的效率是要比Release低的,编译器会针对Release做出许多优化

智能指针的性能问题

unique_ptr的性能是比shared_ptr更具性能的

C++中的random

摸了,下次一定

posted @ 2020-10-25 15:56  _FeiFei  阅读(600)  评论(0编辑  收藏  举报