测量C++程序运行时间
有个很奇怪的现象,我自认为写得好的文章阅读量只有一百多,随手写的却有一千多——要么是胡搞,要么是比较浅显。纵观博客园里众多阅读过万的文章,若非绝世之作,则必为介绍入门级知识的短文。为了让我的十八线博客上升到十七线,我打算写几篇短文。当然,短不等于随便,不等于不负责任。客观的,要有确凿的依据,代码必须调通;主观的,观点尽量全面。
前两天写C++值多态,最后有一个性能比较,需要测量程序运行的时间,于是我重温了相关知识,现整理如下。
C风格
在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++风格
从C++11起,C++提供了更加现代的时间工具,定义在<chrono>
中,namespace std::chrono
下。
chrono
库主要定义了三种类型:时钟(clock)、时间点(time point)和时间段(duration)。时钟产生时间点,时间点相减得到时间段,时间点加减时间段得到时间点。由于有auto
自动类型推导和运算符重载的存在,我们在使用时很少需要写明与时间相关的变量的类型。
C++标准规定了3种时钟:
system_clock
,系统范围的挂钟,可以理解为桌面右下角的时钟,这个时钟是可以调节的,因此system_clock
的返回值可能不是单调的;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);
}
测量C++程序运行时间的更多相关文章
- C#测量程序运行时间及cpu使用时间
转载:http://www.cnblogs.com/yanpeng/archive/2008/10/15/1943369.html 对一个服务器程序想统计每秒可以处理多少数据包,要如何做?答案是用处理 ...
- C#测量程序运行时间及cpu使用时间实例方法
private void ShowRunTime() { TimeSpan ts1 = Process.GetCurrentProcess().TotalProcessorTime; Stopwatc ...
- 检测Java程序运行时间的2种方法(高精度的时间[纳秒]与低精度的时间[毫秒])
第一种是以毫秒为单位计算的. 代码如下: long startTime=System.currentTimeMillis(); //获取开始时间 doSomeThing(); //测试的代码段 lon ...
- PAT乙级 1026. 程序运行时间(15)
1026. 程序运行时间(15) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 要获得一个C语言程序的运行时间, ...
- VC中监测程序运行时间(二)-毫秒级
/* * 微秒级计时器,用来统计程序运行时间 * http://blog.csdn.net/hoya5121/article/details/3778487#comments * //整理 [10/1 ...
- PAT-乙级-1026. 程序运行时间(15)
1026. 程序运行时间(15) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 要获得一个C语言程序的运行时间, ...
- java中读取程序运行时间
第一种是以毫秒为单位计算的. Java代码 //伪代码 long startTime=System.currentTimeMillis(); //获取开始时间 doSomeThing(); // ...
- Java计算两个程序运行时间
一.获取系统当前时间 long startTime = System.currentTimeMillis(); //获取开始时间 doSomething(); //测试的代码段 long endTim ...
- 三种计算c#程序运行时间的方法
三种计算c#程序运行时间的方法 第一种: 利用 System.DateTime.Now // example1: System.DateTime.Now method DateTime dt1 = S ...
随机推荐
- 【Weiss】【第03章】练习3.20:中缀表达式转后缀表达式
[练习3.20] a.编写一个程序将中缀表达式转换为后缀表达式,该中缀表达式含括号及四则运算. b.把幂操作符添加到你的指令系统中去. c.编写一个程序将后缀表达式转化为中缀表达式. Answer: ...
- http详解和分析
1.http是什么? http 是一种超文本传输协议原名是这个Hypertext Transfer Protocol -- HTTP/1.1 可以百度查看http的RFC文档编号为RFC-2616 连 ...
- JAVA-阿里云短信服务
1.引入相关依赖 <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> < ...
- vscode如何配置debug,python正则表达式如何匹配括号,关于python如何导入自定义模块
关于vscode如何配置debug的问题: 1.下载安装好python,并且配置好 环境变量 2.https://www.cnblogs.com/asce/p/11600904.html 3.严格按照 ...
- 2. python提示:TypeError: unhashable type: 'list'
原因是,python字典的key不支持list类型和dict类型,需要转换 错误时 将list类型强制转换成string,用"".join(list). 修改后:
- 从零开始学习R语言(二)——数据结构之“因素(Factor)”
本文首发于知乎专栏:https://zhuanlan.zhihu.com/p/60101041 也同步更新于我的个人博客:https://www.cnblogs.com/nickwu/p/125370 ...
- 记一次RSA解密过程
有问题可以评论 openssl rsa -pubin -text -modulus -in warmup -in pub.key
- eclipse、 IDEA中字母大小写转换快捷键
eclipse 中字母大小写切换快捷键: ctrl + shift + x 转为大写 ctrl + shift + y 转为小写 IDEA 中字母大小写切换快捷键: ctr + sh ...
- springMVC容器简介和执行流程
先来看一下,初始化的大体流程: 然后,我们再来看一下,我们的控制器DispatcherServlet的类图及继承关系. 系统启动的时候根据配置文件创建spring的容器, 首先是发送http请求到 ...
- 汉诺塔Java实现
public class Hanoi { public static void main(String[] args ) { Hanoi hanoi = new Hanoi(); hanoi.hano ...