性能测试的时间间隔获取方法

来源:互联网 发布:协同过滤算法讲解 编辑:程序博客网 时间:2024/04/28 16:03

转自http://blog.csdn.net/gengshenghong/article/details/6973086

性能测试的时候,一个问题就是时间间隔,有很多时间函数能获取时间,从而求取时间间隔。关于这方面的文章很多,我就不重复了,这里只是提供一些基本的信息,从而方便我自己做性能测试使用:

(1)C语言时间函数clock()和clock_t:

time.h中的C语言时间函数clock()能获取当前时间。需要注意的是,这个函数在Windows和Linux下是通用的,但是其返回值的单位是不同的,一个是毫秒,一个是微秒。

从单位也可以看出该方式获取时间的精度。总体来说,其精度在毫秒级,所以测试性能的时候,对于粗时间间隔的测试,用这个函数就足够了。

需要注意的是:在Linux上,clock()获取的是CPU时间,不是wall-clock时间,所以如果使用了sleep()等函数,那么是不会计算在内的。但是在Windows平台上,clock()获取的时间包括Sleep()等函数的时间,所以使用clock()的时候要注意这一点,在Linux上得到的很可能不是一个正确的Elapsed time

(2)利用CPU获取高精度时间rdtsc寄存器

rdtsc是一个64位的寄存器,新的CPU都具备这个寄存器,用于记录从计算机启动开始CPU经过的时钟周期,可见其精度之高是和CPU的频率级别的。

可以参考http://blog.sina.com.cn/s/blog_5d9051c00100jcsn.html的文章。

由于是寄存器,所以只要使用汇编读取寄存器的值就可以得到时间了,具体关于汇编的写法有一些不同的形式,具体可以参考网上的写法,而且windows和Linux下也可能是有一些区别。需要注意的是,即使都是在Linux下或都是Windows下,编译64位和32位的时候,其写法也会不一样,参考:http://www.phpzy.com/php/1068620.html和http://www.uplook.cn/index-Index-show-view2681.html?treeid=624(如果错误使用,得到的时间间隔可能为负数)

PS:在Linux上,-m32和-m64选项分别表示生成32位和64位程序,使用-m32会定义__i386__宏,使用-m64则使用__x86_64__宏。

关于Windows上,也可以使用rdtsc寄存器,但是windows上生成64位程序的时候,不知道该如何获得正确值,参考http://sunxiunan.com/?p=983里面有64位的情况,但是只能用于Itanium CPU上。根据MSDN的说明(http://msdn.microsoft.com/en-us/library/ee417693.aspx),不建议使用rdtsc寄存器,建议使用更精确的windows API的QueryPerformanceCounter和QueryPerformanceFrequency。

(3)Windows平台的QueryPerformanceCounter和QueryPerformanceFrequency的使用:

参考:http://www.oschina.net/code/snippet_197161_6789

(4)Timing.h和测试:

下面是能运行于Linux和Windows的代码,可以用于计算程序运行时间,对于一样的性能测试,应该可以胜任。

  1. // Timing.h  
  2. #ifndef TIMING_H  
  3. #define TIMING_H  
  4.   
  5. #include <time.h>  
  6. #include <stdio.h>  
  7.   
  8. #ifdef WIN  
  9. #include <windows.h>  
  10. #define timing_t double  
  11. static _LARGE_INTEGER time_start, time_over;  
  12. static double dqFreq;  
  13.   
  14. static inline void startTiming()  
  15. {  
  16.     _LARGE_INTEGER f;  
  17.     QueryPerformanceFrequency(&f);  
  18.     dqFreq=(double)f.QuadPart;  
  19.       
  20.     QueryPerformanceCounter(&time_start);  
  21. }  
  22.   
  23. // unit: ms  
  24. static inline timing_t stopTiming()  
  25. {  
  26.     QueryPerformanceCounter(&time_over);  
  27.     return ((double)(time_over.QuadPart-time_start.QuadPart)/dqFreq*1000);  
  28. }  
  29.   
  30. static inline timing_t stopWithPrintTiming()  
  31. {  
  32.     timing_t timing;  
  33.     QueryPerformanceCounter(&time_over);  
  34.     timing = ((double)(time_over.QuadPart-time_start.QuadPart)/dqFreq*1000);  
  35.     printf("----------Elapsed Timing(ms) : %.3lf\n", timing);  
  36.     printf("----------------------------------------\n");  
  37.   
  38.     return timing;  
  39. }  
  40.   
  41. #else  
  42. #include <unistd.h>  
  43. typedef unsigned long long int64;  
  44. #define timing_t int64  
  45. #if defined(__i386__)  
  46. inline int64 GetCycleCount() {  
  47.     int64 result;  
  48.     __asm__ __volatile__ ("rdtsc" : "=A" (result));  
  49.     return result;  
  50. }  
  51. #elif defined(__x86_64__)  
  52. inline int64 GetCycleCount()   
  53. {  
  54.     int64 hi, lo;  
  55.     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));  
  56.     return ( (int64)lo)|( ((int64)hi)<<32 );  
  57. }  
  58. #endif  
  59.   
  60. static int64 ticks_start, ticks_end;  
  61.   
  62. static inline void startTiming()  
  63. {  
  64.     ticks_start = GetCycleCount();  
  65. }  
  66.   
  67. // unit: cycles  
  68. static inline int64 stopTiming()  
  69. {  
  70.     ticks_end = GetCycleCount();  
  71.     return (ticks_end - ticks_start);  
  72. }  
  73.   
  74. static inline int64 stopWithPrintTiming()  
  75. {  
  76.     int64 timing;  
  77.     ticks_end = GetCycleCount();  
  78.     timing = (ticks_end - ticks_start);  
  79.     printf("----------Elapsed Timing(Cycles) : %llu\n", timing);  
  80.     printf("----------------------------------------\n");  
  81.   
  82.     return timing;  
  83. }  
  84. #endif  
  85.   
  86. // unit: ms  
  87. static inline void wait(int ms)  
  88. {  
  89. #ifdef WIN32  
  90.     Sleep(ms);  
  91. #else  
  92.     usleep(ms*1000);  
  93. #endif  
  94. }  
  95.   
  96. #endif  

  1. // foo.cpp  
  2. #include "timing.h"  
  3.   
  4. int main()  
  5. {  
  6.     timing_t ticks_start, ticks_end;  
  7.     startTiming();  
  8.   
  9.     wait(3000); // 3 seconds  
  10.     timing_t timing = stopWithPrintTiming();  
  11.       
  12.     return 1;  
  13. }  

Windows上编译:cl foo.cpp /DWIN,分别启动64bit和32bit的VS控制台进行测试。

Linux上编译:gcc foo.cpp -m32和gcc foo.cpp -m64进行测试。


0 0