天天看點

Linux下的函數執行時間的統計方法

  如何測試某個函數的執行時間是做實驗時經常用到的功能,在此比較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。

繼續閱讀