目前,根本没有办法精确测量程序运行时间,但可用两类方法进行估测:一是基于计时器Timer,一是基于计数器Counter。
一) 基于Timer的测量方法
缺点:精度不够,不能用于程序运行持续时间小于100ms的测量
优点:准确性不是十分依赖于系统负载,并且在执行时间大于1s的程序上,与理论值之间的误差很低
方法:在程序开始时读取计时器的内容,在程序终止前再次读取Timer的内容。
接口函数:
(1)Unix/Linux
clock_t times(struct tms *buf);
//return value:系统自启动以来经过的时间滴答数,常数CLK_TCK表示每秒经过的时钟滴答数
//parameter:一个指向tms结构的指针
//使用该函数时要包含头文件
(2)Win32
DWORD GetTickCount(VOID)
//return value:the number of milliseconds that have elapsed since the system was started.
//使用时应包含
//link阶段应链接 kernel32.lib
(3)可平台移植的代码
clock_t clock(void)
//常数CLOCKS_PER_SEC保证将该函数返回的值格式化为秒
//使用该函数时要包含头文件
/////////////////////////////////////////// C++
#include
using namespace std;
///////////////////////////////////////////
clock_t start, finish;
double duration;
start = clock();
//type your tested code here
finish = clock();
duration = (double)(finish – start) / CLOCKS_PER_SEC;
printf(“%f seconds\n”, duration);
system(“pause”);//经典的程序暂停法
二)基于Counter的测量方法
缺点:只能用汇编语言读取,不能保证通用性,在系统负载很大的情况下,将极大的影响准确性
优点:精度高,并且因为得到的是程序执行期间所经过的时钟周期数,所以可大致估算出在不同硬件平台上程序的执行时间
方法:在IA32体系结构中,CPU内部有一个被称为“时间戳(TimeStamp)”的64位无符号数计数器,存储自cpu上电以来所经过的时钟周期数
(1)WIN32
有一个QueryPerformanceCouter函数读取的就是64位的计数器.
(2)目前的compiler有的不支持RDTSC指令,如果在这种compiler下,可以利用__emit指令绕过compiler执行,应该在文件头加入:
#define CPUID __asm __emit 0fh __asm __emit 0a2h
#define RDTSC __asm __emit 0fh __asm __emit 031h
微软的C/C++编译器从6.0版开始支持CPUID和RDTSC指令,所以可以直接在程序中嵌入汇编代码,下面是一个简单示例:
#include
int main()
{
unsigned int cycle,i;
__asm
{
CPUID
RDTSC
mov cycle,eax
}
for(i=0;i<10000;i++)
;
__asm
{
CPUID
RDTSC
sub eax,cycle
mov cycle,eax
}
printf("the program duration cycle = %d\n",cycle);
return 0;
}
由于基于counter的测量方法受影响的因素较多,主要是Context Switch和Instruction Cache的影响,所以高精度计时必须设法消除上述两种因素的影响,对Context Switch主要是采用在负载低的机器上多次计算求平均,而对Instruction Cache多采用提前载入需要测试代码段的Instruction,然后执行测量的方法.
具体做法参见 Computer System: A programmer's perspective(Chapter 7)
例子:
1#include “time.h”
2
3// 时间变量与时间函数
4clock_t tstart = 0;
5
6
7void Settime()
8 {
9 tstart = clock();
10}
11
12
13double Gettime()
14 {
15 return (double)((double)clock() – (double)tstart)/(double)CLOCKS_PER_SEC;
16}
17
18
19
20int main()
21{
22 Settime();//开始计时
23 /**//****
24 do something ****/
25
26 cout << "-->监视耗时 : ” ;
27 cout << Gettime()<< endl ;
28
29 return 1;
30}