有个很奇怪的现象,我自认为写得好的文章阅读量只有一百多,随手写的却有一千多——要么是胡搞,要么是比较浅显。纵观博客园里众多阅读过万的文章,若非绝世之做,则必为介绍入门级知识的短文。为了让个人十八线博客上升到十七线,我打算写几篇短文。固然,短不等于随便,不等于不负责任。客观的,要有确凿的依据,代码必须调通;主观的,观点尽可能全面。html
前两天写C++值多态,最后有一个性能比较,须要测量程序运行的时间,因而我重温了相关知识,现整理以下。ios
在C程序和C++11之前的C++程序中,测量程序运行时间通常使用clock
函数和CLOCKS_PER_SEC
常量,定义在<time.h>
中。并发
clock_t
是一种能表示时钟周期数的算术类型,在MSVC和GCC中都是long
。函数
clock
函数返回自一个与程序执行相关的时间起至调用时刻通过的时钟周期数,类型为clock_t
。因为起始时间是由实现定义的,clock
函数的返回值没有直接的意义,只有两次调用clock
的结果之差才有意义。工具
CLOCKS_PER_SEC
表示一秒有多少个时钟周期,在MSVC和GCC中都是1000
,即C风格时间测量的精度为1毫秒。若是long
的大小是4字节,clock
溢出须要24天,通常状况下足够使用。性能
#include <stdio.h> #include <time.h> int work() { int sum = 0; for (int i = 0; i < 1e8; ++i) sum += i * i; return sum; } int main() { clock_t start, finish; start = clock(); volatile int result = work(); finish = clock(); printf("%fms\n", (double)(finish - start) / CLOCKS_PER_SEC * 1000); }
从C++11起,C++提供了更加现代的时间工具,定义在<chrono>
中,namespace std::chrono
下。this
chrono
库主要定义了三种类型:时钟(clock)、时间点(time point)和时间段(duration)。时钟产生时间点,时间点相减获得时间段,时间点加减时间段获得时间点。因为有auto
自动类型推导和运算符重载的存在,咱们在使用时不多须要写明与时间相关的变量的类型。spa
C++标准规定了3种时钟:线程
system_clock
,系统范围的挂钟,能够理解为桌面右下角的时钟,这个时钟是能够调节的,所以system_clock
的返回值可能不是单调的;code
steady_clock
,稳定的、单调的时钟,不受系统时间调节的影响,于是适合于测量时间间隔,一般测量程序运行时间就用steady_clock
;
high_resolution_clock
,可用的最高精度的时钟,能够是上面两个的别名。
每一个时钟都有静态方法now
返回当前的时间点,is_steady
常量表示时钟是否单调(steady_clock::is_steady
必定为true
)。system_clock
是惟一能与C中time_t
互通的时钟。
时钟定义了成员类型period
,表示一个时钟周期的时长(以秒为单位)。在MSVC和GCC中,steady_clock::period
都是nano
,理论上的分辨率为纳秒。
两个时间点相减能够获得时间段,调用其count
函数能够得到其数值,这个时间段的类型是由实现定义的。标准还定义了milliseconds
、seconds
等类型,为了获得以咱们想要的单位表示的时间段,能够用duration_cast
来转换:
#include <iostream> #include <chrono> int work() { int sum = 0; for (int i = 0; i < 1e8; ++i) sum += i * i; return sum; } int main() { auto start = std::chrono::steady_clock::now(); volatile int result = work(); auto finish = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(finish - start); std::cout << duration.count() << "ms" << std::endl; }
可是这样只能输出整数毫秒,若是想要更精确一点,一种方法是转换成microseconds
之后除以1000.0
,更优雅地能够本身定义一种时间段类型,如duration<double, milli>
,其中double
表示这种时间段类型用double
来存储时钟周期数量,milli
表示时钟周期为1ms。从由整数表示的duration
到由浮点数表示的duration
的转换能够由duration
的构造函数来完成,无需再用duration_cast
:
auto start = std::chrono::steady_clock::now(); volatile int result = work(); auto finish = std::chrono::steady_clock::now(); using milliseconds = std::chrono::duration<double, std::milli>; milliseconds duration = finish - start; std::cout << duration.count() << "ms" << std::endl;
另外一个与时间相关的经常使用功能是程序睡眠,在C++11之前没有标准的函数能够实现,C++11引入的并发解决了这个需求。
std::this_thread::sleep_for
用于使当前线程挂起一段时间,其参数类型为duration
模板实例,能够用milliseconds(100)
等建立,也能够在using namespace std::chrono_literals
后直接写100ms
(须要C++14)。参数不是普通整数,也就没有了时间单位上的歧义。
#include <chrono> #include <thread> using namespace std::chrono_literals; int main() { std::this_thread::sleep_for(100ms); }