【原創】linux實時操作系統xenomai x86平臺基準測試(benchmark)

一、前言

benchmark 即基準測試。通常操作系統主要服務於應用程序,其運行也是需要一定cpu資源的,一般來說操作系統提供服務一定要快,否則會影響應用程序的運行效率,尤其是實時操作系統。所以本文針對操作系統來做一些基準測試,看看在低端x86平臺上,xenomai提供我們平時常用的服務所需要的時間,清楚地瞭解該平臺上一些xenomai服務的消耗,有時能有利於我們進一步優化程序。影響因素有:主機CPU的結構、指令集以及CPU特性、運算速度等。

目前大多商業實時操作系統會提供詳細benchmark測試,比如VxWorks,目前xenomai沒有這類的方式,所以借鑑VxWorks的測試方式,對xenomai進行同樣測試,所以文章中的測試項命名可能在Linux開發人員看來有點彆扭,切勿見怪,其中一些具體流程可見本博客另外一篇文章xenomai與VxWorks實時性對比(資源搶佔上下文切換對比)

測試環境:

CPU:Intel j1900

內存:4GB DDR3

注:測試數據僅供個人參考,單位us,每項測試次數500萬次,編寫測試用例使用的接口爲Alchemy API,原因主要是Alchemy API比較好編寫。

二、 測試數據處理

對於每個基準測試,通過在操作前讀取時間戳\(t1\),該操作完成後讀取時間戳\(t2\)\(t2\)\(t1\)之間的差值就是測該操作的耗時。

1.1 測試注意事項

需要注意的是,由於我們是基準測試,所以\(t1\)~\(t2\)這段時間儘量不要被不相關的事務打斷,比如處理不相關的中斷、非測試範圍內的任務搶佔等。爲此需要考慮如下。

① 執行測試操作的任務優先級必須最高,兩個任務間交互的測試類似。

② 必須檢測t1-t2之間的非相關中斷,並丟棄對應的測試數據,由於我們已將非xenomai的中斷隔離到其cpu0,且無其他實時設備中斷,除各種異常外,剩下與xenomai相關的就是定時器中斷了,所以僅對tick中斷處理,如果測試過程中產生了定時器中斷,則忽略這組數據,因此需要爲xenomai添加一個系統調用來獲取中斷信息,測試前後通過該系統調用獲中斷信息,以此判斷測試的過程中有沒有中斷產生。

③ 讀取時間戳的操作也是需要執行時間的,所以需要從結果中減去該時間的影響,測量讀取時間戳的需要的時間很簡單,通過連續兩次讀取時間戳\(a1\),\(a2\),\(a2-a1\)就是函數 _M_TIMESTAMP()的執行需要時間。

1.2 數據的處理

得到無誤的操作耗時、測試次數後計算平均值最大值、最小值即可;

1.3 測試結構

根據以上,每個測試的流程及代碼結構如下:

① 讀取起始tick

② 開始測試循環

③ 讀取時間戳a

④ 讀取起始時間戳b

被測試的操作

⑥讀取結束時間戳c

⑦判斷是否是loadrun,是則丟棄本次結果跳轉到③

⑧讀取tick,判斷本次測試是否位於同一tick內,否則丟棄本次結果跳轉到③

⑨判讀耗時是都正確(a-b且b-c爲正值),是則爲有效值,否則丟棄本次結果跳轉到③

	unsigned long  a;
    unsigned long  b;
    unsigned long  c;
    ULONG	   tick;
    BOOL	   loadRun = TRUE;  /*排除cache對測試的影響,丟棄第一次測試的數據*/

    tick = tickGet();  /*確保測試在同一個tick內完成*/

 	/*循環測試iterations次操作並統計結果*/
    for (counter = 0; counter < pData->iterations; counter++)
	{	
    
	a = _M_TIMESTAMP();
	b = _M_TIMESTAMP();  /*起始時間*/
	
        wd = wdCreate ();/*測試的操作*/

	c = _M_TIMESTAMP();	/*結束時間*/
        
	/*數據統計處理*/
	BM_DATA_RECORD (((c >= b) && (b >= a)), c - b, b - a,
			counter, tick, loadRun);
	}

二、測試項

明白數據統計處理後剩下的就是其中測試的具體操作了,benchmark 分別對二值信號量(semB)、計數信號量(semC)、互斥量(semM)、讀寫信號量(SemRW)、任務(Task)、消息隊列(msgq)、事件(event)、 中斷響應(interrupt)、上下文切換(contexswitch)、時鐘抖動(TaskJitter、IntJitter)在各種可能的情況下,測試該操作的耗時。

2.1 時間戳

測試讀時間戳耗時bmTimestampRead

 	unsigned long a;
    unsigned long b;
    ULONG	  tick;
    BOOL	  loadRun = TRUE;					\

    tick = tickGet();

    for (counter = 0; counter < pData->iterations; counter++)
        {
	a = _M_TIMESTAMP();
	b = _M_TIMESTAMP();

	/* validate and record data */

	BM_DATA_RECORD ((b > a), b - a, 0, counter, tick, loadRun);
	}

min avg max
0.084 0.094 0.132

2.2 任務切換

2.2.1信號量響應上下文切換時間

bmCtxSempend: 同一cpu上,高優先級任務對空信號量P操作阻塞,到低優先任務激活的時間。

bmCtxSemUnpend: 同一cpu上,低優先級任務對信號量V操作到高優先任務激活的時間。

CtxSmpAffinitySemUnPend: 高低優先級任務運行於不同cpu上,高優先級任務對空信號量P操作阻塞,到低優先任務激活的時間。

CtxSmpNoAffinitySemUnPend: 不設置親和性,隨系統調度,低優先級任務對信號量V操作到高優先任務激活的時間。

min avg max
bmCtxSempend 2.136 2.193 2.641
bmCtxSemUnpend 2.351 2.395 2.977
CtxSmpAffinitySemUnPend 0.000 0.752 2.642
CtxSmpNoAffinitySemUnPend 2.389 2.454 2.797
2.2.2消息隊列響應上下文切換時間

bmCtxMsgqPend:同一cpu上,高優先級任務對空消息隊列接收數據阻塞,到低優先任務激活的時間。

bmCtxMsgqUnpend:同一cpu上, 低優先級任務寫消息隊列到高優先任務激活的時間。

CtxSmpAffinityMsgQUnPend:高低優先級任務運行於不同cpu上,高優先級任務對空消息隊列接收數據阻塞,到低優先任務激活的時間。

CtxSmpNoAffinityMsgQUnPend:不設置親和性,隨系統調度, 低優先級任務寫消息隊列到高優先任務激活的時間。

min avg max
bmCtxMsgqPend 2.496 2.529 2.833
bmCtxMsgqUnpend 2.882 2.949 3.374
CtxSmpAffinityMsgQUnPend 5.245 5.497 10.589
CtxSmpNoAffinityMsgQUnPend 2.941 2.995 3.636
2.2.3事件響應上下文切換時間

bmCtxMsgqPend:高優先級任務接收事件阻塞,到低優先任務激活的時間。

bmCtxMsgqUnpend: 低優先級任務發送事件到高優先任務激活的時間。

min avg max
bmCtxEventPend - - -
bmCtxEventUnpend - - -
CtxSmpAffinityEventQUnPend - - -
CtxSmpNoAffinityEventUnPend - - -
2.2.2.4任務上下文切換時間

bmCtxTaskSwitch:同一cpu上,優先級調度下的任務切換時間。

min avg max
bmCtxTaskSwitch 0.703 1.633 2.594

2.3 信號量(Semaphore)

1. 信號量的創建與刪除

bmSemBCreate: 創建一個信號量耗時。

bmSemBDelete: 刪除一個信號量耗時。

min avg max
bmSemCreate 10.433 11.417 12.977
bmSemDelete 10.276 11.431 12.317
2. 信號量PV操作

SemGiveNoTask:當沒有任務阻塞在信號量上時,對空信號量V操作消耗的時間。

SemGiveTaskInQ:同一CPU上,高優先級任務阻塞在信號量時,低優先級任務釋放信號量操作消耗的時間。

SemTakeUnavail:單任務對不可用的信號量P操作消耗的時間。

SemTakeAvail:單任務對可用信號量非阻塞P操作消耗的時間。

bmSemGiveTake:單任務對同一信號量連續一次PV操作消耗的時間。

min avg max
SemGiveNoTask 0.099 0.110 0.132
SemGiveTaskInQ 1.837 2.036 2.281
SemTakeAvail 0.084 0.094 0.108
SemTakeUnavail 0.111 0.125 0.144
SemGiveTake 0.187 0.192 0.198
SemPrioInv 6.531 6.842 11.968

2.4 互斥量(Mutex)

2.4.1 互斥量的創建與刪除

MutexCreate:創建一個互斥量耗時。

MutexDelete:刪除一個互斥量耗時。

2.4.2 互斥量PV操作

MutexGiveNoTask:當沒有任務阻塞在mutex上時,釋放mutex操作消耗的時間。

MutexGiveTaskInQ:同一CPU上,高優先級任務阻塞在mutex時,低優先級任務釋放mutex操作消耗的時間。

MutexTakeUnavail:當沒有mutex可用時,對mutex請求操作的耗時。

MutexTakeAvail:在mutex可用時,請求mutex消耗的時間。

MutexGiveTake:單任務對mutex連續請求釋放消耗的時間。

min avg max
MutexCreate 2.881 2.947 3.205
MutexDelete 2.039 2.084 2.209
MutexGiveNoTask 0.033 0.044 0.066
MutexGiveTaskInQ 0.047 0.117 0.228
MutexTakeAvail 0.084 0.094 0.114
MutexGiveTake 0.118 0.122 0.148

2.5 消息隊列(Message Queue)

2.5.1 創建與刪除

MsgQCreate:創建一個MsgQ需要的時間。

MsgQDelete:刪除一個MsgQ需要的時間。

2.5.2 數據收發

MsgQRecvAvail:當MsgQ內有數據時,接收1Byte數據需要的時間。

MsgQRecvNoAvail:當MsgQ沒有數據時,非阻塞接收1Byte數據需要的時間。

MsgQSendPend:高優先級等待數據時,發送1Byte數據需要的時間。

MsgQSendNoPend:沒有任務等待數據時,發送1Byte數據需要的時間。

MsgQSendQFull:當MsgQ滿時,非阻塞發送1Byte數據需要的時間。

min avg max
MsgQCreate 5.991 6.324 6.855
MsgQDelete 3.733 3.849 4.046
MsgQRecvAvail 0.240 0.279 0.396
MsgQRecvNoAvail 0.216 0.267 0.349
MsgQSendPend 2.401 2.647 3.902
MsgQSendNoPend 1.223 1.262 1.536
MsgQSendQFull 0.228 0.275 0.408

2.6 定時器(Alarm)

AlarmCreate:創建一個alarm的時間。

AlarmDelStarted:刪除一個已經激活的alarm的時間。

AlarmDelNotStarted:刪除一個未激活alarm的時間。

AlarmStartQEmpty:任務沒有alarm時,start一個alarm需要的時間。

AlarmStartQEmpty:任務在已有一個 alarm的基礎上,再start一個alarm需要的時間。

AlarmCancel:stop一個alarm需要的時間。

min avg max
AlarmCreate 4.790 4.937 7.719
AlarmDelStarted 3.637 3.804 4.250
AlarmDelNotStarted 3.420 3.523 4.381
AlarmStartQEmpty 1.860 2.079 3.158
AlarmStartQFull 1.835 1.897 2.101
AlarmCancel 1.596 1.680 2.677

2.7 事件(Event)

EventSendSelf: 任務向自己發送一個Event需要的時間。

EventReceiveAvailable: 接收一個已產生的Event需要的時間。

EventReceiveUnavailable: 非阻塞接收一個未產生的Event需要的時間。

EventTaskSendWanted: 高優先級等待Event時,發送Event需要的時間。

EventTaskSendUnwanted: 無任務等待Event時,發送Event需要的時間。

min avg max
EventSendSelf 4.790 4.937 7.719
EventReceiveAvailable 3.637 3.804 4.250
EventReceiveUnavailable 3.420 3.523 4.381
EventTaskSendWanted 1.860 2.079 3.158
EventTaskSendUnwanted 1.835 1.897 2.101

2.8 任務(Task)

2.8.1 任務創建激活

TaskSpawn: 創建並激活一個任務需要的時間。

TaskDelete:刪除一個任務需要的時間。

TaskInit:創建一個任務需要的時間。

TaskActivate:激活新創建的任務需要的時間。

2.8.2 任務調度控制

TaskSuspendReady:對一個已經處於ready狀態的任務suspend操作需要的時間。

TaskSuspendPend:對一個等待資源處於pend狀態的任務進行suspend操作需要的時間。

TaskSuspendSusp:對剛創建的處於Suspend任務 執行Suspend操作需要的時間。

TaskSuspendDelay:對一個處於sleep任務進行suspend操作需要的時間。

TaskResumeReady:對一個處於Ready狀態的任務進行Resume操作需要的時間。

TaskResumePend:對一個等待資源處於pend狀態的任務進行Resume操作需要的時間。

TaskResumeSusp:對一個處於Suspend狀態的任務進行Resume操作需要的時間。

TaskResumeDelay:對一個處於sleep任務進行Resume操作需要的時間。

TaskPrioritySetReady:對一個處於Ready狀態任務修改優先級操作需要的時間。

TaskPrioritySetPend:對一個處於pend狀態任務修改優先級操作需要的時間。

bmTaskCpuAffinityGet:獲取任務的親和性需要的時間。

bmTaskCpuAffinitySet:設置任務的親和性需要的時間。

min avg max
TaskSpawn(1000萬次) 150.649 153.859 1162.041
TaskDelete(1000萬次) 136.074 145.766 189.952
TaskInit(1000萬次) 178.703 185.015 436.639
TaskActivate 1.052 1.336 2.986
TaskSuspendReady 1.404 1.444 1.681
TaskSuspendPend 0.035 1.392 1.561
TaskSuspendSusp 0.151 0.155 0.321
TaskSuspendDelay 1.356 1.401 1.525
TaskResumeReady 0.146 0.155 0.487
TaskResumePend 0.756 0.802 0.877
TaskResumeSusp 0.204 0.248 0.324
TaskResumeDelay 0.180 0.228 0.300
TaskPrioritySetReady 18.925 21.002 21.855
TaskPrioritySetPend 19.046 21.014 28.296
TaskCpuAffinityGet - - -
TaskCpuAffinitySet 8.332 9.541 19.808

Cyclic:如下操作的流程循環一次的耗時,圖中M表示mutex,B表示Semaphore。

/*
       Higher Priority 	   Lower Priority
		 Task1			   			Task2
		=============== 		   ==============


	   semTake(M)
	   semGive(M)
		 |
		 V
	   semGive(B)
	   semTake(B)
		 |
		 V
	   semTake(B)
		 \
		  \
		   \------------->	  semTake(M)
							  semGive(B)
									  /
									 /
	   semTake(M)	  <-------------/
		 \
		  \
		   \------------->	  semGive(M)
									  /
									 /
	   semGive(M)	  <-------------/
		 |
		 V
	   taskSuspend()  <-------------/
		 \
		  \
		   \------------->	  taskResume()
								      /
									 /
	   msgQSend()	  <-------------/
	   msgQReceive()
		 |
		 V
	   msgQReceive()
		 \
		  \
		   \------------->	  msgQSend()
									  /
									 /
	   taskDelay(0)   <-------------/
		 |
		 V
	   eventReceive()
		 \
		  \
		   \------------->	  eventSend()
									  /
									 /
	   repeat...	  <-------------/
*/
min avg max
Cyclic 33.589 34.409 36.471

版權聲明:本文爲本文爲博主原創文章,轉載請註明出處。如有問題,歡迎指正。博客地址:https://www.cnblogs.com/wsg1100/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章