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
代表时间间隔的类型,可以是double
,float
,int
,long long
等等。
Period
代表周期,它的类型std::ratio
也是一个模板类,它两个非类型模板参数,其中std::intmax_t
为long 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}$
duration
和ratio
的第二个模板参数都有默认值,以下方代码为例:时间间隔的类型为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::ratio
在duration
类中的运用可以理解成是单位,比方说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::system_clock,具体可参阅CppReference-system_clock
- std::chrono::steady_clock,具体可参阅CppReference-steady_clock
- std::chrono::high_resolution_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
推断出来的start
是std::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
摸了,下次一定