关闭

财富坊cff888: c++11 chrono全面解析(最高可达纳秒级别的精度)

标签: chronoc++11时间库计时用法
1676人阅读 评论(2) 收藏 举报
分类:

chrono是c++ 11中的时间库,提供计时,时钟等功能。

学习chrono,关键是理解里面时间段(Durations)、时间点(Time points)的概念。

1.精度:

时钟节拍(时间精度):

template <intmax_t N, intmax_t D = 1> class ratio;
其中N表示分子,D表示分母默认用秒表示的时间单位

N对应于其成员num,D对应于其成员den

常用的单位:

ratio<60, 1>? ??? ??? ??? ??? ??minute

ratio<1, 1>? ??? ??? ??? ??? ????second

ratio<1, 1000>? ??? ??? ??? ?microsecond

...

ratio主要是是为后面将要讲解的时间段,时间点等提供精度(单位)

#include<iostream>
#include<chrono>
using namespace std;
int main()
{
	cout << "millisecond : ";
	cout << std::chrono::milliseconds::period::num << "/" << std::chrono::milliseconds::period::den << "s" <<endl;
	system("pause");
	return 0;
}

2.时间段:

template <class Rep, class Period = ratio<1> >
class duration;
std::chrono::duration 表示一段时间,比如两个小时,12.88秒,半个时辰,一炷香的时间等等

Rep表示一种数值类型,用来表示Period的数量,比如int float double。
Period是ratio类型,用来表示上面所说的单位精度,比如second milisecond。
chrono中宏定义了许多特例化了的duration:
就是常见的hours,miniutes,seconds,milliseconds等,使用std::chrono::milliseconds直接使用。
(1)构造函数很简单
(1)duration() = default;    //默认构造
(2)duration (const duration& dtn);        //(2)(3)拷贝构造
(3)template<class Rep2, class Period2>
   constexpr duration (const duration<Rep2,Period2>& dtn);
(4)template<class Rep2>      //传递一个某类型(int等)的数值,构造一个时间段   
   constexpr explicit duration (const Rep2& n);

(2)成员函数count()返回单位时间的数量。

#include <iostream>
#include <chrono>
int main()
{
	std::chrono::milliseconds mscond(1000); // 1 second
	std::cout << mscond.count() << " milliseconds.\n";

	std::cout << mscond.count() * std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;
	std::cout << " seconds.\n";
	system("pause");
	return 0;
}

(2)当不要求截断值的情况下(时转换成秒是没问题,但是秒转换成时就不行)时间段的转换是隐式
的。显示转换可以由 std::chrono::duration_cast<> 来完成。
比如 std::chrono::milliseconds ms(54802);

std::chrono::seconds s=std::chrono::duration_cast<std::chrono::seconds>(ms);

这里的结果就是截断的,而不是进行了舍入,所以s最后的值将为54。

3.时间点:

template <class Clock, class Duration = typename Clock::duration>
  class time_point;

std::chrono::time_point 表示一个具体时间,如上个世纪80年代、今天下午3点、火车出发时间等,只要它能用计算机时钟表示。

第一个模板参数Clock用来指定所要使用的时钟(标准库中有三种时钟,system_clock,steady_clock和high_resolution_clock。见4时钟详解),第二个模板函数参数用来表示时间的计量单位(特化的std::chrono::duration<> )

时间点都有一个时间戳,即时间原点。chrono库中采用的是Unix的时间戳1970年1月1日 00:00。所以time_point也就是距离时间戳(epoch)的时间长度(duration)。

(1)构造函数:

(1)
time_point();           //默认构造函数,时间戳作为其值
(2)
template <class Duration2>
time_point (const time_point<clock,Duration2>& tp);  //拷贝构造函数
(3)
explicit time_point (const duration& dtn);           //使用duration构造,就是距离时间戳的时间长度
(2)时间点有个重要的函数:duration time_since_epoch() ?(用于获取当前时间点距离时间戳的时间长度)

即经常用来得到当前时间点到1970年1月1日00:00的时间距离、该函数返回的duration的精度和构造time_point的时钟(Clock)有关(见4时钟详解)。

#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
int main()
{
	//距离时间戳2两秒
	chrono::time_point<chrono::system_clock, chrono::seconds> tp(chrono::seconds(2));
	cout << "to epoch : " <<tp.time_since_epoch().count() << "s" <<endl;
	//转化为ctime,打印输出时间点
	time_t tt = chrono::system_clock::to_time_t(tp);
	char a[50];
	ctime_s(a, sizeof(a), &tt);
	cout << a;
	system("pause");
	return 0;
}

可以看出,时间戳就是使用的Unix的时间戳。

4.时钟:(代表当前系统的时间)

chrono中有三种时钟:system_clock,steady_clock和high_resolution_clock。每一个clock类中都有确定的time_point, duration, Rep, Period类型。

system_clock是不稳定的。因为时钟是可调的,即这种是完全自动适应本地账户的调节。这种调节可能造成的是,首次调用now()返回的时间要早于上次调用now()所返回的时间,这就违反了节拍频率的均匀分布。稳定闹钟对于超时的计算很重要,所以C++标准库提供一个稳定时钟 std::chrono::steady_clock。std::chrono::high_resolution_clock 是标准库中提供的具有最小节拍周期(因此具有最高的精度的时钟)。

上文所说time_since_epoch(),以及将要介绍的now()函数的返回值都依赖于时钟的精度,测试时钟的精度的一种方法就是:

#include <iostream>
#include <chrono>
using namespace std;
int main()
{
	cout << "system clock          : ";
	cout << chrono::system_clock::period::num << "/" << chrono::system_clock::period::den << "s" << endl;
	cout << "steady clock          : ";
	cout << chrono::steady_clock::period::num << "/" << chrono::steady_clock::period::den << "s" << endl;
	cout << "high resolution clock : ";
	cout << chrono::high_resolution_clock::period::num << "/" << chrono::high_resolution_clock::period::den << "s" << endl;
	system("pause");
	return 0;
}

windows系统的测试结果是system_clock的精度是100纳秒,而high_resolution的精度是1纳秒,对于程序来说,一般毫秒级就够了,所以说chrono提供的时钟精度绰绰有余。

(1)成员函数static time_point now() noexcept; 用于获取系统的当前时间。

(2)由于各种time_point表示方式不同,chrono也提供了相应的转换函数 time_point_cast。

template <class ToDuration, class Clock, class Duration>
  time_point<Clock,ToDuration> time_point_cast (const time_point<Clock,Duration>& tp);
传一个要转换为的精度的duration模板参数和一个要转换的time_point参数(用法见下面综合应用)

(3)其他成员函数:

to_time_t() time_point转换成time_t秒

from_time_t() 从time_t转换成time_point

综合应用:

输出当前时间,并且计算当前的时间距离1970年1月1日00:00的毫秒数

#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
int main()
{
	//定义毫秒级别的时钟类型
	typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
	//获取当前时间点,windows system_clock是100纳秒级别的(不同系统不一样,自己按照介绍的方法测试),所以要转换
	microClock_type tp = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
	//转换为ctime.用于打印显示时间
	time_t tt = chrono::system_clock::to_time_t(tp);
	char _time[50];
	ctime_s(_time,sizeof(_time),&tt);
	cout << "now time is : " << _time;
	//计算距离1970-1-1,00:00的时间长度,因为当前时间点定义的精度为毫秒,所以输出的是毫秒
	cout << "to 1970-1-1,00:00  " << tp.time_since_epoch().count() << "ms" << endl;
	system("pause");
	return 0;
}


通过两张图片对比,时间点上相差48-34=14秒、、下面的一长串数字,切掉3位(毫秒)、是28-14=14秒、、正确!说明这一串数字的最后三位就是毫秒数、、充分说明了达到了毫秒级别。

将上面的程序中millisconds换成microseconds或者更小的单位,便可达到微妙,甚至更高的精度。

3
0
查看评论

C++11 chrono全面解析(最高可达纳秒级别的精度)

[ 转载自 ](/bc5/qq_31175231/article/details/77923212) chrono是c++ 11中的时间库,提供计时,时钟等功能。 学习chrono,关键是理解里面时间段(Durations)、时间点(Time points)的概念。...
  • Y__Jason
  • Y__Jason
  • 2017-09-20 11:36
  • 122

在内核获取时间 精度纳秒级

原文地址:http://blog.chinaunix.net/uid-20583479-id-1920140.html 程序代码:     struct timespec ts;     ts = current_kern...
  • zahuopuboss
  • zahuopuboss
  • 2015-03-31 15:40
  • 687

Linux时钟精度:毫秒?微妙?纳秒?

扫盲:1秒=1000毫秒=1000000微妙=1000000000纳秒 首先:linux有一个很重要的概念——节拍,它的单位是(次/秒)。2.6内核这个值是1000,系统中用一个HZ的宏表征这个值。同时有全局的jiffies变量,表征从开机以来经过的节拍次数(这里面还有故事,后面说,先记住这个...
  • charleslei
  • charleslei
  • 2016-09-05 12:44
  • 3057

C++11标准库chrono

chrono是C++11新加入的方便时间日期操作的标准库,它既是相应的头文件名称,也是std命名空间下的一个子命名空间,所有时间日期相关定义均在std::chrono命名空间下。通过这个新的标准库,可以非常方便进行时间日期相关操作。 chrono库主要包含了三种类型:duration, time_...
  • u010487568
  • u010487568
  • 2016-01-13 19:35
  • 1501

[C/C++11]_[初级]_[实用时间库chrono]

场景 C++11开始提供了一个 实用时间库,相比C的time_t强多了,最明显的是可以精确到纳秒. vs2010还不支持这个库,所以比较可惜,对于新开发的项目,建议用2015可以使用最新特性. 一般用这个库来转换时间或计算函数执行时间或者CPU指令周期. 例子 #include <iostre...
  • infoworld
  • infoworld
  • 2016-05-30 14:30
  • 3024

C++11 新的计时方法——std::chrono 大法好

C++11里面提供了很多炫酷的新标准。我以下给出采用 C++11 标准的”最佳计时方法“的代码:
  • u013390476
  • u013390476
  • 2015-12-16 19:33
  • 13182

C++11新特性,利用auto和std::chrono获取系统时间的方法

const std::string getCurrentSystemTime() { auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); struct tm* ptm = localt...
  • zjc156m
  • zjc156m
  • 2016-12-22 15:26
  • 648

纳秒级延时实例。

HANDLE hTimer = NULL; LARGE_INTEGER liDueTime; //创建等待句柄  hTimer = CreateWaitableTimerA(NULL, TRUE, “myNsWait”); if (!hTimer) {   ...
  • liuyi820729
  • liuyi820729
  • 2016-09-22 11:14
  • 547

C++11的chrono库,可实现毫秒微秒级定时

C++11有了chro #include usingnamespace std; usingnamespace std::chrono;   classTimer { public:     Tim...
  • u201011221
  • u201011221
  • 2014-06-05 11:08
  • 6078

C++11新特性,利用std::chrono精简传统获取系统时间的方法

C++11新特性,利用std::chrono精简传统获取系统时间的方法
  • q229827701
  • q229827701
  • 2014-11-11 19:10
  • 4138
    个人资料
    • 访问:11807次
    • 积分:459
    • 等级:
    • 排名:千里之外
    • 原创:32篇
    • 转载:3篇
    • 译文:0篇
    • 评论:6条
    最新评论