如何測試某個函數的執行時間是做實驗時經常用到的功能,在此比較Linux下的測試函數,主要是其精确度。我們采用統一的測試标準程式(standard.c):
#include <stdio.h>
#define MAX 1000
int do_work()
{
int counter = 0;
int i, j;
for(i = 0; i < MAX; i++)
for(j = 0; j < MAX; j++)
counter++;
return counter;
}
int main()
{
printf("counter = %d/n", do_work());
}
通過指令gcc -o standard standard.c生成測試程式。
Linux下的方法:
(1) 使用指令time:
[[email protected] xgf]# time ./standard
counter = 1000000
real 0m0.006s
user 0m0.000s
sys 0m0.000s
time指令對秒(s)級别的很精确,而對毫秒級的誤差比價大。我們可以通過sleep/usleep函數來進行測試。sleep(0.1)或者usleep(100)都是表示休眠100ms,而測試結果都是:
real 0m0.002s
user 0m0.000s
sys 0m0.000s
(2) 通過difftime函數:
double difftime(time_t time1, time_t time0);計算time1和time0之間的秒數。測試程式如下:
#include <stdio.h>
#include <time.h>
#define MAX 1000
int do_work()
{
int counter = 0;
int i, j;
for(i = 0; i < MAX; i++)
for(j = 0; j < MAX; j++)
counter++;
return counter;
}
int main()
{
time_t start, end;
int val;
start = time(NULL);
do_work();
end = time(NULL);
printf("val = %f/n", difftime(end, start));
return 0;
}
測試結果如下:
val = 0.000000
real 0m0.006s
user 0m0.000s
sys 0m0.000s
我們發現,difftime的精确度還沒有time指令高。
(3) 通過gettimeofday函數:
int gettimeofday(struct timeval *tv, struct timezone *tz); 其中timeval結構定義如下:
struct timeval
{
time_t tv_sec;
suseconds_t tv_usec;
};
擷取目前時刻,可以精确到微妙級别。
#include <stdio.h>
#include <sys/time.h>
#define MAX 1000
int do_work()
{
int counter = 0;
int i, j;
for(i = 0; i < MAX; i++)
for(j = 0; j < MAX; j++)
counter++;
return counter;
}
int main()
{
struct timeval start, end;
int interval;
gettimeofday(&start, NULL);
do_work();
gettimeofday(&end, NULL);
interval = 1000000*(end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
printf("interval = %f/n", interval/1000.0);
}
輸出結果如下:
interval = 3.527000
real 0m0.006s
user 0m0.000s
sys 0m0.000s
也就是3.527ms。
(4) 利用rdtsc彙編指令,這是硬體計數器提供的功能,可以精确到1/f(f為處理器頻率)。
#include <stdio.h>
#include <time.h>
#define MAX 1000
#define FREQUENCE 1595984000.00
int do_work()
{
int counter = 0;
int i, j;
for(i = 0; i < MAX; i++)
for(j = 0; j < MAX; j++)
counter++;
return counter;
}
int main()
{
unsigned int start_high, start_low;
unsigned int end_high, end_low;
long long interval, start, end;
asm("rdtsc /n/t");
asm("movl %%eax, %0/n/t":"=g"(start_low));
asm("movl %%edx, %0/n/t":"=g"(start_high));
printf("start_high:/t%08X start_low:/t%08X/n", start_high, start_low);
start = start_high;
start = (start << 32) | start_low;
do_work();
asm("rdtsc /n/t");
asm("movl %%eax, %0/n/t":"=g"(end_low));
asm("movl %%edx, %0/n/t":"=g"(end_high));
printf("end_high:/t%08X end_low:/t%08X/n", end_high, end_low);
end = end_high;
end = (end << 32) | end_low;
interval = end - start;
printf("lost time is:/t%llX %f/n", interval, (interval * 1000)/FREQUENCE);
return 0;
}
輸出結果如下:
start_high: 00013272 start_low: A1081568
end_high: 00013272 end_low: A1600586
lost time is: 57F01E 3.611002
real 0m0.006s
user 0m0.000s
sys 0m0.000s
綜上所述,time指令和difftime函數基本都是秒級别的,根本達不到毫秒級别的計數。而gettimeofday和rdtsc是很精确的方式,建議如果大家以後需要毫秒級别的計數采用gettimeofday或者rdtsc。