Not Only Algorithm,不仅仅是算法,关注数学、算法、数据结构、程序员笔试面试以及一切涉及计算机编程之美的内容 。。
你的位置:NoAlGo博客 » 程序设计 » ,

Windows计时函数

评估程序的运行效率是程序设计过程中经常遇到的需求,一般可以在程序代码段的首尾分别记录当时的时间,然后相减得到程序运行的实际时间,时间越长说明效率越低,需要想办法优化。
Windows平台下提供了许多API函数来完成这个功能,本文将简单介绍常用的几种方法,不同方法有不同的精度和运行环境要求,可以根据不同的情况适当选择。

计时函数

为了以实际的代码说明各个API的使用方法及效果,本文对以下代码的运行时间进行计算,具体是一个简单的空循环以达到消耗一定时间的目的。

for (volatile int i = 0; i < (1 << 30); i++);

volatile关键字说明变量i可能会被意想不到地改变,然后编译器就不会去假设这个变量的值了,每次用到这个变量时都必须小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份,这样可以确保本条指令不会因编译器的优化而省略。如果没有这个关键字,则该段代码在Release模式下编译时一般会被优化掉,于是测试其运行时间就变得没有意义。
注意这个代码的实际运行时间并不是固定的,可能每一次运行的时间都不一样,以下的输出结果仅选择其中一个。

time

time函数可以返回以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数。其函数原型为:

time_t time(time_t *timer);

具体例子如下:

#include <cstdio>
#include <ctime>
#include <Windows.h>
int main()
{
	time_t st = time(NULL);
	for (volatile int i = 0; i < (1 << 30); i++);
	time_t ed = time(NULL);
	printf("Time: %ds\n", ed - st); //Time: 2s
}

clock

clock函数可以返回进程启动到调用函数时所经过的CPU时钟计时单元数,以毫秒为单位。其函数原型为:

clock_t clock(void);

具体例子如下:

#include <cstdio>
#include <ctime>
#include <Windows.h>
int main()
{
	clock_t st = clock(); 
	for (volatile int i = 0; i < (1 << 30); i++);
	clock_t ed = clock();
	printf("Time: %dms\n", ed - st); //Time: 2071ms
}

timeGetTime

timeGetTime函数返从系统启动到调用函数时所经过的毫秒数,以毫秒为单位。其返回值是一个双字,值在0到2^32之间。大约49.71天。其函数原型为:

DWORD timeGetTime(VOID);

使用时需要链接winmm.lib,可以用以下方法之一:

  • 代码中添加#pragma comment( lib,"winmm.lib" )
  • 在Visual Studio的“项目–属性–链接器–输入–附加依赖性”中,添加winmm.lib。

具体例子如下:

#include <cstdio>
#include <Windows.h>
#include <mmsystem.h>
#pragma comment(lib, "Winmm.lib")
int main()
{
	DWORD st = timeGetTime();
	for (volatile int i = 0; i < (1 << 30); i++);
	DWORD ed = timeGetTime();
	printf("Time: %dms\n", ed - st); //Time: 2105ms
}

GetTickCount

GetTickCount函数返回从操作系统启动所经过的毫秒数,返回值以32位的双字类型DWORD存储,因此可以存储的最大值是2^32ms约为49.71天,因此若系统运行时间超过49.71天时,这个数就会归0。其函数原型为:

DWORD WINAPI GetTickCount(void);

具体例子如下:

#include <cstdio>
#include <Windows.h>
int main()
{
	DWORD st = GetTickCount();
	for (volatile int i = 0; i < (1 << 30); i++);
	DWORD ed = GetTickCount();
	printf("Time: %dms\n", ed - st); //Time: 2106ms
}

高精度计时

Windows提供的高精度计时器,在一些较老的系统中可能无法使用。首先使用以下API获取计时器的计时频率:

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

然后再待测代码前后使用如下API获取时间:

BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

最后二者相减并除以计时频率可以得到经过的时间。具体例子如下:

#include <cstdio>
#include <Windows.h>
int main()
{
	LARGE_INTEGER tem;
	QueryPerformanceFrequency(&tem);
	double dff = tem.QuadPart;

	QueryPerformanceCounter(&tem);
	__int64 st = tem.QuadPart;

	for (volatile int i = 0; i < (1 << 30); i++);

	QueryPerformanceCounter(&tem);
	__int64 ed = tem.QuadPart;

	printf("Time: %fms\n", (ed - st) * 1000 / dff); //Time: 2016.642623ms
}
上一篇: 下一篇:

我的博客

NoAlGo头像编程这件小事牵扯到太多的知识,很容易知其然而不知其所以然,但真正了不起的程序员对自己程序的每一个字节都了如指掌,要立足基础理论,努力提升自我的专业修养。

站内搜索

最新评论