[導(dǎo)讀]這篇筆記有如下內(nèi)容: 1、為什么需要計算各個線程的CPU使用率? 2、該如何計算線程CPU使用率? 3、FreeRTOS線程計算的弊端?如何打破 FreeRTOS 線程計算方式的時間限制? 4、關(guān)鍵代碼介紹。 上次介紹了如何計算整個系統(tǒng)的CPU使用率: 《 單片機里面的CPU使用
3、FreeRTOS線程計算的弊端?如何打破 FreeRTOS 線程計算方式的時間限制?
上次介紹了如何計算整個系統(tǒng)的CPU使用率:
但是卻沒有介紹該如何計算每個線程(任務(wù))的CPU使用率。
首先要問的是,為什么要計算線程的CPU使用率,有啥用?
我們知道系統(tǒng)的CPU使用率關(guān)注的是整個系統(tǒng)的使用情況,使用率越低,表示越能更及時的響應(yīng)外部情況,整個系統(tǒng)的性能也會越好。
但這是從系統(tǒng)整體考量的,并不能反映單個線程的執(zhí)行情況。
比如雖然整體的CPU使用率是30%,但是有一個線程占據(jù)了25%的使用率,一個線程使用率是5%,那么你肯定會想,為啥這個線程需要占用這么高的CPU使用率,是不是代碼寫的有問題,是不是代碼可以優(yōu)化一下?
當(dāng)系統(tǒng)運行時,如果你能實時觀察各個線程的CPU使用率,那么你就能知道平時這個線程的CPU使用情況是怎樣的,為什么后來又高那么多,那么你就可以由此分析出這個線程可能出現(xiàn)了問題,也就可以針對性的進行檢查了。
這點對于合作開發(fā)的項目更是明顯,很多時候因為有些線程的代碼不是自己寫的,所以根本不知道代碼執(zhí)行情況,一旦系統(tǒng)出現(xiàn)問題,那么可能就是互相甩鍋了。
而當(dāng)計算了線程的CPU使用率,一旦發(fā)現(xiàn)某個線程執(zhí)行異常,那么就能交給負(fù)責(zé)的人去查看了。
所以說,使用操作系統(tǒng)的項目是非常有必要計算各個線程(任務(wù))的CPU使用率的。
就好比你的電腦,風(fēng)扇嗡嗡響(CPU高負(fù)荷運行),如果只有一個系統(tǒng)CPU使用率,發(fā)現(xiàn)高達90%,但是你卻根本不知道為什么這么高,所以只能重啟。
而一旦有了進程CPU使用率,查看一下哪個進程CPU使用率高,把對應(yīng)的進程關(guān)閉就行了,根本不需要重啟電腦。
那么現(xiàn)在就來看看該如何計算各個線程的CPU使用率。
從前面的筆記,我們其實也可以猜測該如何計算,無非就是獲取
每個線程的執(zhí)行時間罷了。
比如,1秒時間內(nèi),空閑任務(wù)執(zhí)行700毫秒,任務(wù)1執(zhí)行200毫秒,任務(wù)2執(zhí)行100毫秒,那么各個任務(wù)的CPU使用率分別是 70%、20%、10%。
以前計算系統(tǒng)的CPU使用率的時候,采用了軟件方法計算空閑任務(wù)的運行時間,這必然是不夠準(zhǔn)確的,所以最好的方式是采用硬件計時。
因為魚鷹采用STM32F103進行測試,所以使用DWT外設(shè)進行精確計時,不過麻煩的是,在KEIL
軟件仿真情況下,DWT外設(shè)是無法工作的,所以如果要測試的話,必須使用硬件仿真的方式,不過如果真要KEIL軟件仿真的話,也不是沒有辦法,就是使用硬件定時器,這個按下不表。
畢竟,DWT外設(shè)的功能在這里說白了也就是個定時器而已。
既然要獲取線程的執(zhí)行時間,關(guān)鍵一點就是,我們要知道操作系統(tǒng)什么時候會切換到某一個線程運行,什么時候又會從這個線程切出,到另一個線程執(zhí)行呢?
這個關(guān)鍵還是在系統(tǒng)內(nèi)置的
鉤子函數(shù)。上次的筆記魚鷹介紹過空閑鉤子函數(shù),今天介紹另一個鉤子,任務(wù)切換鉤子函數(shù)。
這個鉤子函數(shù)的特點就是,每當(dāng)系統(tǒng)需要切換到下一個任務(wù)時,就會
先執(zhí)行這個函數(shù)。這個函數(shù)一般有兩個參數(shù),
當(dāng)前任務(wù)和
即將切換的任務(wù)。
只要設(shè)置任務(wù)切換的鉤子函數(shù),并且有時間戳,那么計算一個任務(wù)的執(zhí)行時間也就不那么困難了。
比如,操作系統(tǒng)在時刻12345 ms 切換到空閑任務(wù)執(zhí)行,突然一個任務(wù)就緒,開始準(zhǔn)備執(zhí)行,所以在時刻12445切換到那個就緒任務(wù)執(zhí)行,那么空閑任務(wù)的執(zhí)行時間我們也就可以準(zhǔn)確計算出來了。
也就是說,這一次空閑任務(wù)執(zhí)行了 100 毫秒。
如果我們要計算單位時間(比如1秒內(nèi))空閑任務(wù)的執(zhí)行時間,我們只要在每次運行到空閑任務(wù)時
累計時間即可。
比如1秒內(nèi),空閑任務(wù)執(zhí)行了 5 次,分別是 10、200、100、200、50,累計時間為
10 + 200 + 100 + 200 + 50 = 560毫秒
由此,可計算空閑任務(wù)的CPU使用率為 56%,從而可計算出系統(tǒng)的CPU使用率是44%。
是的,通過線程的CPU使用率方法,我們其實也可以計算整個系統(tǒng)的CPU使用率。而且這種計算方式比前面所說的計算方法更準(zhǔn)確,更科學(xué)。
前面采用時間戳進行計算,但是時間戳是會溢出的,那個時候,你的時間計算還是準(zhǔn)確的嗎?
現(xiàn)在魚鷹就來說說第三個問題,F(xiàn)reeRTOS線程計算的弊端?如何打破 FreeRTOS 線程計算方式的時間限制?
從網(wǎng)上查找FreeRTOS任務(wù)CPU計算相關(guān)的資料,可以得到以下信息:
1、需要開一個定時器,這個定時器中斷頻率是操作系統(tǒng)時鐘的十幾倍(為了保證計算精度)。
2、一個64 位的變量在定時器自加更新,一旦變量溢出,時間計算就會出現(xiàn)問題。
(相關(guān)細節(jié)可查看安富萊教程)
第一個問題會導(dǎo)致系統(tǒng)性能下降(中斷頻率太高,一般是微秒級別的),而第二個問題導(dǎo)致在一段時間內(nèi)(小時級別)線程CPU使用率計算準(zhǔn)確,超出時間后,計算會有問題,所以教程中不建議在正式版本加入此功能。
第一個問題其實很好解決,就是使用硬件定時器,不再由CPU去更新時間,這樣不會占用CPU時間,第二個問題其實也非常好解決,就是通過《
延時功能進化論(合集)》的方式解決溢出問題,這里不再展開說其中的奧妙。
任務(wù)切換
鉤子函數(shù)的實現(xiàn)
總之,魚鷹接下來的實現(xiàn)方式解決了以上兩個痛點,即使無限執(zhí)行下去,也不會影響到計算精度問題,唯一對系統(tǒng)產(chǎn)生的一點影響,只有在任務(wù)切換時消耗的一點計算時間(微秒級別)。
那么先上任務(wù)切換
鉤子函數(shù)關(guān)鍵實現(xiàn)代碼(RT-Thread):
void thread_stats_scheduler_hook(struct rt_thread *from, struct rt_thread *to)
{
static uint32_t schedule_last_time;
uint32_t time;
time = get_curr_time();
from->user_data += (time - schedule_last_time);
schedule_last_time = time;
}
如何將這個函數(shù)注冊到操作系統(tǒng)中被系統(tǒng)調(diào)用呢?
那么現(xiàn)在來分析這個鉤子函數(shù)實現(xiàn):
每次任務(wù)開始切換時,更新這個時間戳,同時累積時間,這個時間保存在當(dāng)前任務(wù)的user_data里面。
假設(shè)系統(tǒng)調(diào)度是從任務(wù)1切換到任務(wù)2,即from為
任務(wù)
1,to為
任務(wù)
2,此時獲取的時間戳為
T1
。
上一次的時間戳我們已經(jīng)通過靜態(tài)變量保留了,這里為T0,那么T1-T0就是from任務(wù)即
任務(wù)
1在本次運行的時間,只要下次運行任務(wù)1時繼續(xù)不斷的累積這個時間,那么就可以得到任務(wù)1的總運行時間。
當(dāng)然我們不可能一直累積下去,不然肯定會溢出,所以隔一段時間就需要清零,這個時間其實就是
線程
CPU
計算的周期。
這里還有一個函數(shù)沒有說,就是 get_curr_time(),在這里使用DWT,為了可以重新實現(xiàn)該函數(shù),魚鷹使用了弱屬性 weak(關(guān)于這個看參考:《
困惑多年,為什么 printf 可以重定向? 》)。
__weak
uint32_t get_curr_time()
{
return DWT->CYCCNT;
}
這里可以看到有個注釋,不要使用 rt_tick_get 函數(shù),為啥?
精度太低,有些任務(wù)本來執(zhí)行了的,但是因為執(zhí)行時間
小于操作系統(tǒng)的時鐘(比如1毫秒),那么就無法累積時間了,那么即使這個任務(wù)運行再多,時間累積也為 0,這肯定是我們不希望看到的。
然后再說一個點,為了簡化代碼(鉤子函數(shù)代碼只有短短幾行),魚鷹這樣的實現(xiàn)是有兩個問題的。
1、首次運行計算有誤,因為靜態(tài)變量應(yīng)該在運行任務(wù)之前就初始化的(不應(yīng)該初始化為 0),而鉤子函數(shù)是在任務(wù)運行之后才調(diào)用的,所以從開機以來的時間被累加到第一個運行任務(wù)中了,這肯定是有問題的,不過后面隨著系統(tǒng)的運行,靜態(tài)變量被持續(xù)更新,就不會再出現(xiàn)這個問題了。
2、為了減少修改,魚鷹把線程的use_data當(dāng)成一個變量使用了,實際上這個變量的功能應(yīng)該是存儲線程私有變量地址的,但是因為魚鷹懶得修改太多代碼,所以直接拿來用了。正因為如此,所以魚鷹添加線程CPU計算時,只要修改很少的代碼就可以了。
目前我們已經(jīng)能夠通過鉤子函數(shù)獲取各個線程的CPU執(zhí)行時間,現(xiàn)在就看該如何計算了。
為了計算各個線程的CPU使用率,我們需要確定計算周期,這里我們可以設(shè)置1秒計算一次。
其次,我們需要確定在哪個任務(wù)執(zhí)行計算。
原理上來說,可以是系統(tǒng)中的任何一個任務(wù),但是為了減少對系統(tǒng)的干擾,可以將計算工作放到優(yōu)先級比較低的任務(wù)中進行,比如空閑任務(wù)。
現(xiàn)在,看看函數(shù)是如何實現(xiàn)的:
void thread_cal_usage(thread_run_info_def *run_info)
{
static uint32_t total_time_last;
uint32_t time, total_time;
struct rt_list_node *node;
struct rt_list_node *list;
struct rt_thread *thread;
uint32_t i;
rt_enter_critical();
time = get_curr_time();
total_time = time - total_time_last;
total_time_last = time;
list = &(rt_object_get_information(RT_Object_Class_Thread)->object_list);
for(i = 0, node = list->next; (node != list) && i < THREAD_NBR_MAX; node = node->next, i++){
thread = rt_list_entry(node, struct rt_thread, list);
run_info[i].name = thread->name;
run_info[i].time = thread->user_data;
thread->user_data = 0;
}
rt_exit_critical();
total_time /= 100;
if(total_time > 0){
for(uint32_t j = i, i = 0; i < j; i++)
{
run_info[i].usage = run_info[i].time / total_time;
}
}
}
注釋已經(jīng)很詳盡了,所以不多做討論。主要說以下幾點:
1、為什么需要關(guān)閉調(diào)度器,可以使用關(guān)中斷嗎?
關(guān)調(diào)度器是為了防止在獲取各個線程執(zhí)行時間時,因為系統(tǒng)調(diào)度而導(dǎo)致執(zhí)行時間被更新,從而導(dǎo)致計算有誤,所以需要關(guān)閉調(diào)度器。
那么為什么不使用關(guān)中斷的方式呢?沒有必要。一旦關(guān)中斷,那么中斷就無法響應(yīng)了,所以在可以關(guān)調(diào)度器的情況下滿足要求,就不應(yīng)該關(guān)中斷。
2、為什么分兩步計算,為什么不將最終的計算放在第一個循環(huán)中執(zhí)行呢?
節(jié)省時間,為了盡量減少關(guān)調(diào)度器的時間,能省一點是一點。畢竟只要能獲取到關(guān)鍵信息,啥時候計算都一樣。
3、因為線程CPU計算周期是自動計算的,所以,計算周期其實就是該函數(shù)的調(diào)用周期,即2秒調(diào)用一次,那么線程CPU計算周期就是2秒,但是需要注意的是,調(diào)用周期必須小于定時器的溢出時間,即當(dāng)你使用 DWT 時,調(diào)用周期應(yīng)該在 60 秒以下(72 M 系統(tǒng)時鐘),否則計算是有問題的。
現(xiàn)在我們已經(jīng)算是完成了線程CPU計算問題,但為了使用方便,我們需要把它打印出來,或者把這些信息字符串化:
void thread_stats_print(void)
{
thread_run_info_def run_info[THREAD_NBR_MAX] = {0};
thread_run_info_def *p_info;
thread_cal_usage(run_info);
rt_kprintf("thread\t\t\ttime\t usage\n");
for(uint32_t i = 0; i < THREAD_NBR_MAX; i++)
{
p_info = &run_info[i];
if(p_info->name != NULL)
{
if(p_info->usage > 0)
{
rt_kprintf("%-16s\t%u\t%2u%%\n",
p_info->name,
(uint32_t)p_info->time,
(uint32_t)p_info->usage);
}
else
{
rt_kprintf("%-16s\t%u\t<1%%\n",
p_info->name,
(uint32_t)p_info->time,
(uint32_t)p_info->usage);
}
}
else
{
break;
}
}
}
這里將
線程名、線程執(zhí)行時間、線程使用率都打印出來了,但是需要注意的是,這里的time 時間單位是定時器的單位,而不是微秒、毫秒,比如如果使用 DWT,那么單位就是 1/72 微秒,即如果 time 值為 1000,那么換算到微秒,應(yīng)該是 1000/72 秒,當(dāng)然了,你也可以在打印的同時就把時間換算一下,這個自由發(fā)揮就好。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。
關(guān)鍵字:
阿維塔
塞力斯
華為
加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...
關(guān)鍵字:
AWS
AN
BSP
數(shù)字化
倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...
關(guān)鍵字:
汽車
人工智能
智能驅(qū)動
BSP
北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...
關(guān)鍵字:
亞馬遜
解密
控制平面
BSP
8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。
關(guān)鍵字:
騰訊
編碼器
CPU
8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。
關(guān)鍵字:
華為
12nm
EDA
半導(dǎo)體
8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。
關(guān)鍵字:
華為
12nm
手機
衛(wèi)星通信
要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...
關(guān)鍵字:
通信
BSP
電信運營商
數(shù)字經(jīng)濟
北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...
關(guān)鍵字:
VI
傳輸協(xié)議
音頻
BSP
北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...
關(guān)鍵字:
BSP
信息技術(shù)
山海路引?嵐悅新程 三亞2024年8月27日 /美通社/ --?近日,海南地區(qū)六家凱悅系酒店與中國高端新能源車企嵐圖汽車(VOYAH)正式達成戰(zhàn)略合作協(xié)議。這一合作標(biāo)志著兩大品牌在高端出行體驗和環(huán)保理念上的深度融合,將...
關(guān)鍵字:
新能源
BSP
PLAYER
ASIA
上海2024年8月28日 /美通社/ -- 8月26日至8月28日,AHN LAN安嵐與股神巴菲特的孫女妮可?巴菲特共同開啟了一場自然和藝術(shù)的療愈之旅。 妮可·巴菲特在療愈之旅活動現(xiàn)場合影 ...
關(guān)鍵字:
MIDDOT
BSP
LAN
SPI
8月29日消息,近日,華為董事、質(zhì)量流程IT總裁陶景文在中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式上表示,中國科技企業(yè)不應(yīng)怕美國對其封鎖。
關(guān)鍵字:
華為
12nm
EDA
半導(dǎo)體
上海2024年8月26日 /美通社/ -- 近日,全球領(lǐng)先的消費者研究與零售監(jiān)測公司尼爾森IQ(NielsenIQ)迎來進入中國市場四十周年的重要里程碑,正式翻開在華發(fā)展新篇章。自改革開放以來,中國市場不斷展現(xiàn)出前所未有...
關(guān)鍵字:
BSP
NI
SE
TRACE
上海2024年8月26日 /美通社/ -- 第二十二屆跨盈年度B2B營銷高管峰會(CC2025)將于2025年1月15-17日在上海舉辦,本次峰會早鳥票注冊通道開啟,截止時間10月11日。 了解更多會議信息:cc.co...
關(guān)鍵字:
BSP
COM
AI
INDEX
上海2024年8月26日 /美通社/ -- 今日,高端全合成潤滑油品牌美孚1號攜手品牌體驗官周冠宇,開啟全新旅程,助力廣大車主通過駕駛?cè)ヌ剿鞲鼜V闊的世界。在全新發(fā)布的品牌視頻中,周冠宇及不同背景的消費者表達了對駕駛的熱愛...
關(guān)鍵字:
BSP
汽車制造
此次發(fā)布標(biāo)志著Cision首次為亞太市場量身定制全方位的媒體監(jiān)測服務(wù)。 芝加哥2024年8月27日 /美通社/ -- 消費者和媒體情報、互動及傳播解決方案的全球領(lǐng)導(dǎo)者Cis...
關(guān)鍵字:
CIS
IO
SI
BSP
上海2024年8月27日 /美通社/ -- 近來,具有強大學(xué)習(xí)、理解和多模態(tài)處理能力的大模型迅猛發(fā)展,正在給人類的生產(chǎn)、生活帶來革命性的變化。在這一變革浪潮中,物聯(lián)網(wǎng)成為了大模型技術(shù)發(fā)揮作用的重要陣地。 作為全球領(lǐng)先的...
關(guān)鍵字:
模型
移遠通信
BSP
高通
北京2024年8月27日 /美通社/ -- 高途教育科技公司(紐約證券交易所股票代碼:GOTU)("高途"或"公司"),一家技術(shù)驅(qū)動的在線直播大班培訓(xùn)機構(gòu),今日發(fā)布截至2024年6月30日第二季度未經(jīng)審計財務(wù)報告。 2...
關(guān)鍵字:
BSP
電話會議
COM
TE
8月26日消息,華為公司最近正式啟動了“華為AI百校計劃”,向國內(nèi)高校提供基于昇騰云服務(wù)的AI計算資源。
關(guān)鍵字:
華為
12nm
EDA
半導(dǎo)體