一種簡單、實用的測量程序運行時間的方法
掃描二維碼
隨時隨地手機(jī)看文章
點擊上方「嵌入式大雜燴」,選擇「置頂公眾號」第一時間查看嵌入式筆記!
前言
平時我們可能很少去關(guān)注程序運行的時間,但是在一些情況下可能需要對程序進(jìn)行一個整體的復(fù)盤、優(yōu)化。
那么,程序運行的時間就是一個可以考慮的方面,可以測一下某些代碼塊、函數(shù)、算法的運行時間,然后整體考慮看看有沒有必要進(jìn)行優(yōu)化。
之前在某工控類項目中,我就有接到一個任務(wù)去測試程序中關(guān)鍵代碼的執(zhí)行時間,并輸出報告。當(dāng)時是使用一個GPIO+示波器
進(jìn)行測試的,也可以使用邏輯分析儀來測。
當(dāng)時測量的方法很簡單:
在要測試的代碼塊/函數(shù)之前設(shè)置該GPIO的電平為高電平,在要測試的代碼塊/函數(shù)之后設(shè)置該GPIO為低電平,使用示波器測高電平的時間,就知道了這一代碼塊/函數(shù)的運行時間。
下面就通過實例來介紹一下這種簡單而有效的方法。
我這里使用邏輯分析儀來測量,使用小熊派開發(fā)板
來驗證,小熊派的主控為STM32L431RCT6
,系統(tǒng)時鐘設(shè)置為80MHz
。
這里順帶提一點題外話,之前有一些初學(xué)的讀者朋友問我說邏輯分析儀貴不貴。邏輯分析儀有貴的也有便宜的,貴則上千上萬元,便宜則有幾十、幾百。我覺得無論工作、還是學(xué)習(xí),都有必要入手一個邏輯分析儀。
本篇筆記的測試用的邏輯分析儀就是某寶上二十幾塊錢買的,可以滿足平時的學(xué)習(xí)所用。條件有限的學(xué)生朋友可以入手。有條件的可以考慮入手幾百塊錢的。
GPIO+邏輯分析儀測時間
1、測量HAL_Delay函數(shù)
STM32的HAL庫有給我們提供一個HAL_Delay
延時函數(shù),這是一個ms級延時函數(shù)。這個延時函數(shù)依賴于系統(tǒng)滴答定時器,所以是一個比較精確的延時函數(shù)。
這里,我們就使用GPIO+邏輯分析儀
的方法來測量一下這個延時函數(shù)。為了方便測試,我們在while死循環(huán)里進(jìn)行測量。
代碼:
測量結(jié)果:
可見,我們通過邏輯分析儀測出了HAL_Delay(100);
運行的時間為100.4315ms
,符合我們的預(yù)期。
這里高電平兩側(cè)其實就是低電平部分,只不過低電平持續(xù)的時間太短了,在這里看起來像一條豎線,我們放大來看看:
結(jié)果已經(jīng)很準(zhǔn)了,可以滿足平時的測量。這種測量很難保證百分之百的精確,小數(shù)點后面的那一部分可能是受很多不可控因素的影響,這不在我們本篇文章的討論范圍之內(nèi)。
我們是想通過這個示例來介紹這種測量方法的使用及證明這種方法是可行的。下面再繼續(xù)看兩個實例。
2、測量軟件延時函數(shù)
我們以前剛開始學(xué)單片機(jī)的時候,經(jīng)常有用到一些粗略的延時函數(shù),其實現(xiàn)方法就是循環(huán)執(zhí)行n條空語句,以達(dá)到一個延時的效果。
那么,我們怎么來構(gòu)造一個us級或ms級的粗略延時函數(shù)(軟件延時函數(shù))。我們之前看到的粗略延時函數(shù)類似這樣子:
這些函數(shù)里面需要給出一些循環(huán)的次數(shù),這個值是怎么來確定的呢?比如上面這個函數(shù)中123這個值是怎么來確定的?我們可以使用GPIO+邏輯分析儀的方法
來進(jìn)行一個簡單的確定。
確定1us:
不同的處理器,結(jié)果是不一樣的。針對小熊派開發(fā)板(主控:STM32L431RCT6),循環(huán)運行15條空語句的時間實測結(jié)果是1.083us
,這算是比較接近1us了。
我們就運用這個結(jié)果來構(gòu)建一個us級軟件延時函數(shù)如下:
接下來我們測一下soft_delay_us(100);
實際運行了多長時間:
可見,結(jié)果差不多接近我們想要的結(jié)果。構(gòu)建這樣的粗略延時函數(shù)可以使用這樣的方式來確定一些循環(huán)次數(shù)的值。
3、查表法VS常規(guī)法運行時間
在之前的文章:空間換時間,查表法的經(jīng)典例子《空間換時間,查表法的經(jīng)典例子》中,我們有說可以適當(dāng)使用查表法降低程序的執(zhí)行時間。這里我們來實際測量對比一下那篇文章中查表法與常規(guī)法的優(yōu)劣。
關(guān)鍵代碼:
/* 測試結(jié)果 */
struct test_res
{
unsigned int data; /* 數(shù)據(jù) */
unsigned int count; /* 數(shù)據(jù)中1的個數(shù) */
};
/* ============常規(guī)法============ */
#if 1
struct test_res get_test_res(unsigned int data)
{
/* 保存測試結(jié)果 */
struct test_res res;
/* 保證數(shù)據(jù)總會在0~0xf之間 */
// unsigned int temp = data & 0xf;
unsigned int temp = data & 0xff;
res.count = 0;
res.data = temp;
/* 循環(huán)判斷每一位 */
for (int i = 0; i < 16; i++)
{
if (temp & 0x01)
{
res.count++;
}
temp >>= 1;
}
return res;
}
#else
/* ============查表法============ */
int table[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
struct test_res get_test_res(unsigned int data)
{
/* 保存測試結(jié)果 */
struct test_res res;
/* 保證數(shù)據(jù)總會在0~0xf之間 */
unsigned int temp = data & 0xff;
/* 獲取低4位中1的個數(shù) */
unsigned int low_data = temp & 0xf;
unsigned int low_cnt = table[low_data];
/* 獲取高4位中1的個數(shù) */
unsigned int high_data = (temp >> 4) & 0xf;
unsigned int high_cnt = table[high_data];
/* 結(jié)果 */
res.count = low_cnt + high_cnt;
res.data = temp;
return res;
}
int main(void)
{
/* USER CODE BEGIN 1 */
struct test_res res = {0};
/* 省略部分代碼。。。。。。。。。 */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
res = get_test_res(30);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
}
/* USER CODE END 3 */
}
#endif
常規(guī)法程序的運行時間:
查表法程序的運行時間:
可見,這個例子中常規(guī)法程序運行時間約為2ns,而查表法程序運行時間約為500ns。查表法的程序運行之間僅為常規(guī)法的1/4,省下了3/4的時間。
隨著調(diào)用次數(shù)的增多,這里的查表法的優(yōu)勢越大。比如循環(huán)計算0~31這32個數(shù)中每一個數(shù)二進(jìn)制位為1的個數(shù),則相關(guān)代碼改為:
int i;
while (1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
for (i = 0; i < 32; i++)
{
res = get_test_res(i);
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
}
常規(guī)法:
查表法:
可見,隨著調(diào)用次數(shù)的增多,查表法相對于常規(guī)法更省時,即查表法的優(yōu)勢越大。
以上就是關(guān)于GPIO+邏輯分析儀測程序運行時間
的幾個實例。下面順帶提一下使用MDK+ST-LINK
測STM32程序運行時間的方法。
MDK+ST-LINK測時間
在使用MDK作為開發(fā)工具時,可以搭配一些仿真器來查看程序執(zhí)行時間。這里通過實例來介紹MDK+ST-LINK
測STM32程序運行時間的方法。
這里重點是設(shè)置Trace
里面的系統(tǒng)內(nèi)核時鐘,我們這里使用的是小熊派開發(fā)板(主控:STM32L431RCT6),并且配置的系統(tǒng)時鐘是80MHz:
所以在Trace
中要設(shè)置為80MHz。這個得根據(jù)實際芯片的型號就需要根據(jù)進(jìn)行修改,比如STM32F103系列默認(rèn)是72MHz,STM32F429系列默認(rèn)為180MHz等,根據(jù)實際進(jìn)行修改。
下面我們通過在線調(diào)試、打斷點的方式看一下 HAL_Delay(1000);
運行了多長時間:
可見程序運行到HAL_Delay(1000);
前后的時間分別為:
前:0.00008964s
后:1.00108161s
即HAL_Delay(1000);
走過的時間約為1s,符合預(yù)期。
最后
以上就是本次的實踐分享,感謝閱讀與支持。如有錯誤,歡迎指出。謝謝!
若覺得文章不錯,轉(zhuǎn)發(fā)分享、在看,也是我們繼續(xù)更新的動力。
在公眾號內(nèi)回復(fù)更多資源,可免費獲取嵌入式資料。期待你的關(guān)注~
猜你喜歡
一些不可不知的計算機(jī)網(wǎng)絡(luò)基礎(chǔ)
AT指令測試ESP8266通信模組并獲取天氣數(shù)據(jù)
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!