引言
最近一個項目為了實作低延遲時間、高吞吐的目标,自己寫了個簡單的通信子產品。結合實作中的經驗和看的一些文章,嘗試總結下這個中間一些共通的點,也是做個小結。
備注:我總結時候總是會有一些不同于他人的角度,雖然别人看着可能會比較莫名,但是個人就是寫給未來的自己罷了 O(∩_∩)O哈哈~
備注2:不要來扯什麼中斷、線程排程更靈活之類的廢話。請麻煩認清楚本文讨論的問題。
1. 避免無謂的CPU消耗
1.1 處理線程綁定CPU core
不論是利用使用者态、核心态線程、程序還是自己實作的線程模式,都盡量的避免這中間的排程/切換。主要是為了避免:1.排程消耗 2. 緩存污染,同時有助于實作1.2的原則。
1.2 避免全局變量和其它共享資源
這個當然不完全決定,但是在關鍵路徑上必須的原則。
結合綁定CPU核,可以避免競争,也就不需要各種鎖、信号量等機制。
1.3 輪詢替代中斷
直接涉及硬體裝置驅動時可用,更适合定制化的系統。要知道一個中斷喚醒要3-5us,還不算其它消耗。在高吞吐、高并發下是非常值得采用輪詢模式,更可以結合[1.1]将驅動開始就綁定CPU核處理。
反正就是,一門心思、死心眼的就忙那點事情。多像生産線~~ :)
說到生産線,就引入另一個點,為了能處理各種不同狀況的封包,就需要一個合适的機制給死心眼用
1.4 狀态機值得考慮下
就像生産線上,一個産品(封包)流過不同工序(狀态),每個工序處理一個任務
2. 提升CPU使用率
2.1 批量處理
如果寫個使用者态通信實作,那麼系統調用(TCP協定棧->硬體驅動)是個非常漫長的過程;如果寫個核心态驅動,那麼操作硬體,同樣也是個無法忍受的等待。如果是單并發的系統,還是那話,不在讨論範圍。
批量化的處理,其實就是折疊了這部分系統調用/硬體等較慢處理的消耗,平攤。1個人要捐1萬可能壓力山大,10個人就好多,1000個人就是毛毛雨了。
具體批量處理多少個應根據情況來定,最好有個基準測試和具體的目标,或者可以配置。
2.2 優化記憶體
要知道記憶體配置設定、拷貝甚至查找都是非常耗費時間的。
但是完全的記憶體零拷貝并不見得能實作,需要根據具體的系統、目标,甚至硬體來分析具體實作方案。
但是至少,記憶體池、大頁記憶體在大部分實作中比較容易達到了。
2.3 免鎖實作
嗯,很熱門的CAS實作,隻是這個硬體鎖(原子操作)還是免不掉。同時,如果沖突/競争幾率很高情況下,其實和spinlock也相差無幾。
是以,也許per cpu core的更合适。嗯,至少我還沒想好更好的實作,要努力學習呀!
3. 代碼層面的手段
不多說
3.1 Cache對齊
目前主流的CPU的cache line都是64B長度的,嗯,一次就是刷這麼多。
讀寫的cache适當的分離,避免經常改動的部分影響很少變化的部分。
強烈推薦!
3.2 分支優化(likely/unlikely宏)
小心使用,不完全明确的還是交給CPU自己優化吧
3.3 Cache 預取
在大循環和批量處理,非常有威力。但使用需要些技巧。
3.4 gcc的attribute修飾可以好好研究下
什麼__always_inline__,hot之類
多餘的話
和查找隻會用連結清單逐個比較的,交流如何高性能本身就是挺扯的事情。這說明俺也是個挺扯的人~~
嗯,就這樣~!
本文利用線上Cmd Markdown 編輯閱讀器完成。 https://www.zybuluo.com/wydnpu/note/18095