在Windows中測試c語言單個函數運行時間方法

本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!前端

在作單片機項目開發的過程當中,在特殊應用中對代碼執行的時間有着嚴格的要求,那麼如何準確的測試出每一個函數的的運行速度是多快呢?一般用單片機測試的方法就是經過示波器觀察。ios

好比如今要測試使用二分查找法,在數組中查找一個數字須要屢次時間,測試方法爲:每運行一次查找算法,就讓LED引腳電平翻轉一次,而後使用示波器觀察LED引腳的波形,大概就能測試出這個算法的執行時間了。算法

測試代碼以下:後端

#include "iostm8s103F3.h"
#include "led.h"
#include "find.h"

void sysclkinit( void ) {
    CLK_SWR = 0xe1;       //HSI爲主時鐘源 16MHz CPU時鐘頻率
    CLK_CKDIVR = 0x00;    //CPU時鐘0分頻,系統時鐘0分頻
}

void main( void ) {
    sysclkinit();		          //時鐘初始化
    __asm( "sim" );                       //禁止中斷
    led_init();
    __asm( "rim" );                       //開啓中斷
    while( 1 )
    {   
        LED = !LED;         
        val = binary_search( ( int* )volref, 500, 0, sizeof( volref ) / sizeof( volref[0] ) );   
    }
}
複製代碼

binary_search爲二分查找法函數,在100個數據的數組中查找數字500是否存在,LED每翻轉一次,執行一次函數。而後經過示波器觀察LED的波形。數組

image.png

能夠看到LED引腳的高低電平時間都爲164us,說明這個二分查找法查找數字500所用的時候爲164us。LED引腳自己的翻轉速度小於0.1us,因此LED引腳翻轉自己使用的時間在這裏能夠忽略不計。markdown

這樣在單片機中能夠經過LED引腳的翻轉經過示波器來觀察要測試的函數具體執行所佔用的時間。app

這樣測試積極精確,可是也比較麻煩,每次測試的時候,還必需要經過硬件電路才能測試,那麼能不能不用硬件電路,直接經過軟件測試呢?方法固然是有的,能夠在Windows中在C編譯器中經過軟件仿真,測試每一個函數執行的時間。ide

這裏使用的編譯器爲 Dev-C++,這個編譯器裏面能夠直接運行單片機中寫好的C函數,而後經過系統提供個幾個時間函數,就能夠準確測試出函數運行時間了。函數

image.png

系統提供的能夠測試函數有下面幾個post

  1. clock()函數

The clock() function returns an approximation of processor time used by the program.

The value returned is the CPU time used so far as a clock_t; to get the number of seconds used, divide byCLOCKS_PER_SEC. If the processor time used is not available or its value cannot be represented, the functionreturns the value (clock_t) -1.

簡單而言,就是該程序從啓動到函數調用佔用CPU的時間。這個函數返回從「開啓這個程序進程」到「程序中調用clock()函數」時之間的CPU時鐘計時單元(clock tick)數。

函數原型以下:

image.png

返回值類型爲clock_t,實際上是一個長整形。

image.png

調用這個函數的時候,會返回一個CPU當前時間計數值。要測試時間的話,在函數以前前調用一次clock()函數,將當前時間計數值存儲起來。而後調用要測試的函數,測試函數結束以後,在調用一次clock()函數,讀取當前的時間計數值,而後用這個計數值減去函數執行前的時間計數值,就能夠計算出來函數執行所用的時間,這個時間單位默認爲ms。

2.GetTickCount()函數

GetTickCount返回(retrieve)從操做系統啓動所通過(elapsed)的毫秒數,它的返回值是DWORD,也是一個長整型數。

它的用法和clock()函數基本同樣,在函數執行前調用一次GetTickCount()函數,而後執行函數,函數執行完成後再調用一次GetTickCount()函數,而後計算兩次測時間差,這個單位也是ms。

在Windows系統中感受ms很短,可是對於單片機來講ms時間仍是比較長的,好多函數的執行時間遠遠小於1ms,若是用上面這兩種方法測試的話,許多函數的執行時間是測試不出來的。那麼就須要使用更高精度的測試函數。

  1. QueryPerformanceCounter()函數

調用這個函數會返回硬件支持的高精度計數器的頻率。注意這個返回的是系統的計時器值,不是時間值。上面兩個函數返回的是系統的時間值,而這個函數返回的是系統的計數器值,這個計數器的值至關於時間值來講,精度就高不少了,大多數的精度均可以達到us級。

這個函數在使用前首先要調用QueryPerformanceFrequency()函數獲取系統的計數頻率,也就是1s鍾系統會計數多少次。

而後使用QueryPerformanceCounter()獲取在程序運行先後的計數器值,而後用兩次計數器值的差除以計數的頻率,就能計算出函數執行所使用的時間。

下面開始使用Dev C++軟件測試這三種函數。

編寫測試代碼:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

//待測試函數 
void fun(void) {
	sleep(1);
}
typedef union _LARGE_INTEGER {
	struct {
		long LowPart ;// 4字節整型數
		long  HighPart;// 4字節整型數
	};
	long long QuadPart;// 8字節整型數

} LARGE_INTEGER;

int main(int argc, char *argv[]) {
	int i = 0,val = 0;
	clock_t startTime,endTime;
	int time = 0;
	
	// 方法 1
	startTime = clock();			//計時開始
	fun();					//調用函數 
	endTime = clock();			//計時結束
	printf(" 1:程序運行時間爲: %d ms\r\n\r\n\r\n",(endTime - startTime));

	//方法 2
	startTime = GetTickCount();		//計時開始
	fun();					//調用函數 
	endTime = GetTickCount();		//計時結束
	printf(" 2:程序運行時間爲: %d ms\r\n\r\n\r\n",(endTime - startTime));

	//方法 3
	LARGE_INTEGER secondcount= {0};
	LARGE_INTEGER startcount= {0};
	LARGE_INTEGER stopcount= {0};

	QueryPerformanceFrequency(&secondcount);     //獲取每秒多少CPU Performance Tick 單位us 
	printf(" 3:系統計數頻率爲: %d \r\n",secondcount.QuadPart);

	QueryPerformanceCounter(&startcount);		//計時開始
	fun();						//調用函數 
	QueryPerformanceCounter(&stopcount);		//計時結束
	
	time=( ((stopcount.QuadPart - startcount.QuadPart)*1000*1000)/secondcount.QuadPart);
	printf(" 程序運行時間爲: %d us\r\n\r\n",time);

	system("pause");
	return 0;
}

複製代碼

image.png

運行結果以下

image.png

這裏的測試函數實際爲 sleep(1); 也就是休眠1s鍾,而後使用3種方法分別測試函數執行時間。

使用clock()函數測試代碼執行時間爲1000ms,使用GetTickCount()函數測試代碼執行時間爲998ms,使用QueryPerformanceCounter()函數測試代碼執行時間爲999630us,也就是999.63ms。經過QueryPerformanceFrequency()函數讀取到系統1s鐘的計數次數爲2630703次。

經過系統自帶的時間函數就能夠直接測試每一個函數執行的時間,這樣就能夠不使用硬件電路,就能夠直接對比不一樣的函數執行效率了。

相關文章
相關標籤/搜索