探讨性能测试中的计时问题
摘要:本文结合作者在代码性能测试工作中的经验,介绍一组自己封装的的计时函数。使用该组函数可以简化测试工作,从而把更多的精力放在主要工作上,不需要过多地维护计时代码,仅仅使用两个宏就可以方便、精确地实现多个模块、多方式的时间性能测试,并且计时结果以一个文本文件独立保存,清晰直观。 关键字:精确计时;性能测试; 在系统测试时,尤其在需要测试算法或者某些模块的运行时间时,往往需要调用一些时间函数库(如VC中的timeGetTime等可以获取毫秒级的时间),在待测试的模块前后分别测试时间,然后,计算前后两个时间的差值,就得到模块的运行时间,如图 1。
1. 高精度计时函数 计时之前,调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率,然后在需要计时的模块前后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差获得时钟频率,计算出模块的运行时间。代码如图 2: 图 2 精确计时代码段 2. 封装计时函数 #define BENCHMARK_MAX_COUNT 20 double gStarts[BENCHMARK_MAX_COUNT]; double gEnds[BENCHMARK_MAX_COUNT]; double gCounters[BENCHMARK_MAX_COUNT]; double dfFreq = 1;
2.2. 初始化InitBenchmark()
void InitBenchmark() { ResetBenchmarkCounters(); GetClockFrequent(); } 该函数一般在程序运行最初调用。 2.3. 开始计时BMTimerStart() void BMTimerStart(int iModel) { LARGE_INTEGER litmp; QueryPerformanceCounter(&litmp); gStarts[iModel] = litmp.QuadPart; }其中参数iModel表示当前计时的模块序号,0<=iModel<=BENCHMARK_MAX_COUNT;为了简化调用代码,我们给出一个宏定义如下: #define BM_START(t) BMTimerStart(t);2.4. 终止计时BMTimerEnd() 终止计时函数BMTimerEnd()放在计时模块的结束,函数定义如下: void BMTimerEnd(int iModel) { LARGE_INTEGER litmp; QueryPerformanceCounter(&litmp); gEnds[iModel] = litmp.QuadPart; gCounters[iModel] += (((gEnds[iModel] - gStarts[iModel]) / dfFreq) * 1000000); } 参数iModel同BMTimerStart()。本函数首先获取当前的时钟数,然后除以dfFreq得到运行时间。对于最后一条语句: gCounters[iModel] += (((gEnds[iModel] - gStarts[iModel]) / dfFreq) * 1000000); 要注意两点:
类似BMTimerStart(),同样为BMTimerEnd()定义一个宏: #define BM_END(t) BMTimerEnd(t); 2.5. 结果输出WriteData() 3. 计时测试实例
3.3. 循环累加计时 图 6 累加计时1 图 7 累加计时2
本文实现了一组计时函数的封装,并给出几种特殊情况下的测试实例,实验表明该组函数可以满足各种复杂情况下的计时,能够很方便地应用的实际的测试工作中。当然,还可以进一步封装成一个计时类,留给读者们自己去做。 |
作者:BuildNewApp
出处:http://syxchina.cnblogs.com、 BuildNewApp.com
本文版权归作者、博客园和百度空间共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则作者会诅咒你的。
如果您阅读了我的文章并觉得有价值请点击此处,谢谢您的肯定1。