目前,根本没有办法精确测量程序运行时间,但可用两类方法进行估测:一是基于计时器Timer,一是基于计数器Counter。
一) 基于Timer的测量方法缺点:精度不够,不能用于程序运行持续时间小于100ms的测量
优点:准确性不是十分依赖于系统负载,并且在执行时间大于1s的程序上,与理论值之间的误差很低
方法:在程序开始时读取计时器的内容,在程序终止前再次读取Timer的内容。接口函数:
(1)Unix/Linuxclock_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{ CPUIDRDTSCmov cycle,eax}for(i=0;i<10000;i++);__asm{ CPUIDRDTSCsub eax,cyclemov 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”23// 时间变量与时间函数4clock_t tstart = 0;567void Settime()8 { 9 tstart = clock();10}111213double Gettime()14 { 15 return (double)((double)clock() – (double)tstart)/(double)CLOCKS_PER_SEC;16}17181920int main()21{ 22 Settime();//开始计时23 /**//****24 do something ****/2526 cout << "-->监视耗时 : ” ;27 cout << Gettime()<< endl ;2829 return 1;30}
from: