Linux效能優化實戰CPU篇之總結(四)

MXC肖某某發表於2022-03-03

一、分析CPU瓶頸

1,效能指標

a>CPU使用率

  CPU使用率描述了非空閒時間佔總CPU時間的百分比,根據CPU上執行任務的不同可以分為:使用者CPU、系統CPU、等待I/O CPU、軟中斷和硬中斷等

  • 使用者CPU使用率,包括使用者態CPU使用率(user)和低優先順序使用者態CPU使用率(nice),表示CPU在使用者態執行的時間百分比。使用者CPU使用率高,通常說明有應用程式比較繁忙
  • 系統CPU使用率,表示CPU在核心態執行的時間百分比(不包括中斷)。系統CPU使用率高,說明核心比較繁忙
  • 等待I/O的CPU使用率,通常也稱之為iowait,表示等待I/O的時間百分比。iowait高,通常說明系統與硬體裝置的I/O互動時間比較長。
  • 軟中斷和硬中斷的CPU使用率,分別表示核心呼叫軟中斷處理程式、硬中斷處理程式的時間百分比。它們的使用率高,通常說明系統發生了大量的中斷
  • 竊取CPU使用率(steal)和客戶CPU使用率(guest),分別表示被其他虛擬機器佔用的CPU時間百分比和執行客戶虛擬機器的CPU時間百分比

b>平均負載

  系統的平均活躍程式數。它反應了系統的整體負載情況,主要包括三個數值,分別指過去1分鐘、過去5分鐘和過去15分鐘的平均負載。

  理想情況下,平均負載等於邏輯CPU個數,這表示每個CPU都恰好被充分利用。如果平均負載大於邏輯CPU個數,就表示負載比較重。

c>上下文切換

  • 無法獲取資源而導致的自願上下文切換
  • 被系統強制排程導致的非自願上下文切換

  上下文切換,本身是保證Linux正常執行的一項核心功能。但過多的上下文切換,會將原本執行程式的CPU時間,消耗暫存器、核心棧以及虛擬記憶體等資料的儲存和恢復上,縮短程式真正執行的時間,成為效能瓶頸。

d>CPU的快取命中率

  https://cloud.tencent.com/developer/article/1597149

  CPU的處理速度要比記憶體的訪問速度快很多,CPU在訪問記憶體的時候,就需要等待記憶體的響應。為了協調二者的巨大效能差距,CPU快取(多級快取)就出現了

   

   CPU快取的速度介於CPU和記憶體之間,快取的是熱點的記憶體資料。根據不斷增長的熱點資料,這些快取按照大小不同分為L1、L2、L3等三級快取,其中L1和L2常用在單核中,L3則用在多核中。

  從L1到L3,三級快取的大小依次增大,相應的效能依次降低(當然比記憶體好很多)。而它們的命中率,衡量的是CPU快取的複用情況,命中率越高,則表示效能越好。

2,效能工具

a>平均負載

  uptime檢視系統的平均負載。在平均負載升高時,使用mpstat和pidstat,分別觀察每個CPU和每個程式CPU的使用情況,進而定位負載升高的程式

b>上下文切換

  vmstat檢視系統的上下文切換次數和中斷次數。使用pidstat (-w),觀察程式的自願上下文切換(cswch/s)和非自願上下文切換(nvcswch/s);使用pidstat(-wt)輸出具體執行緒的上下文切換。

c>CPU使用率升高

  使用top觀察具體的CPU情況,然後使用perf工具定位具體的執行緒和函式

d>不可中斷程式和殭屍程式

  top觀察iowait升高,並發現出現大量的zombie殭屍程式,使用dstat定位為磁碟讀取導致,再使用pidstat找出相關程式,最後用perf工具定位原因

e>軟中斷

  top觀察cpu使用率升高,再使用watch -d /proc/softirqs,找到變化速率較快的軟中斷,然後通過sar(-n DEV)顯示網路收發的報告,發現為網路小包問題,最後用tcpdump,找到網路幀的型別和來源,確定為SYNFLOOD攻擊導致。

3,效能指標和效能工具關聯

a>根據指標找工具

   

b>根據工具查指標

   

 c>分析CPU效能瓶頸

  

二、CPU效能優化的思路

1,如何評估效能優化效果

a>確定效能的量化指標

  不要侷限在單一維度的指標上。以web專案為例:

  • 應用程式的維度,可以用吞吐量和請求延遲來評估應用程式的效能
  • 系統資源的維度,可以用CPU使用率來評估系統的CPU使用情況

b>測試優化前的效能指標

c>測試優化後的效能指標

2,CPU優化

a>應用程式優化

  降低CPU使用率的最好方法是排除所有不必要的工作,只保留最核心的邏輯。比如減少迴圈的層次、減少遞迴、減少動態記憶體分配等。

  除此之外,應用程式的優化也包括很多方法,最常用的:

  • 編譯器優化:很多編譯器都會提供優化選項,適當開啟。比如,gcc就提供了優化選項 -O2,開啟後會自動對應用程式的程式碼進行優化。
  • 演算法優化:使用複雜度更低的演算法,可以顯著加快處理速度。比如,在資料比較大的情況下,可以用O(nlogn)的排序演算法(如快排、歸併排序等),代替O(n^2)的排序演算法(如冒泡、插入排序等)。
  • 非同步處理:使用非同步處理,可以避免程式因為等待某個資源而一直阻塞,從而提升程式的併發處理能力。比如,把輪詢替換為事件通知,就可以避免輪詢耗費CPU的問題。
  • 多執行緒代替多程式:相對於程式上下文切換, 執行緒上下文切換並不切換程式選址空間,因此可以降低上下文切換的成本
  • 善用快取:經常訪問的資料或者計算過程中的步驟,可以放到記憶體中快取起來,這樣在下次用時就能直接從記憶體中獲取,加快程式的處理速度。

b>系統優化

  從系統的角度來說,優化CPU的執行,一方面要充分利用CPU快取的本地性,加速快取訪問;另一方面,就是要控制程式的CPU使用情況,減少程式間的相互影響。常見方法:

  • CPU繫結:把程式繫結到一個或者多個CPU上,可以提高CPU快取的命中率,減少跨CPU排程帶來的上下文切換問題
  • CPU獨佔:跟CPU繫結類似,進一步將CPU分組,並通過CPU親和性機制為其分配程式。這樣,這些CPU就由指定的程式獨佔,換句話說,不允許其他程式再來使用這些CPU。
  • 優先順序調整:使用nice調整程式的優先順序,正值調低優先順序,負值調高優先順序。適當降低非核心應用的優先順序,增高核心應用的優先順序,可以確保核心應用得到優先處理。
  • 為程式設定資源限制:使用Linux cgroups 來設定程式的CPU使用上限,可以防止由於某個應用自身的問題,而耗盡系統資源
  • NUMA(Non-Uniform Memory Accesss)優化:支援NUMA的處理器會被劃分為多個node,每個node都有自己的本地記憶體空間。NUMA優化,其實就是讓CPU儘可能只訪問本地記憶體。
  • 中斷負載均衡:無論軟中斷還是硬中斷,它們的中斷處理程式都可能會耗費大量的CPU。開啟irqbalance服務或者配置smp_affinity,就可以吧中斷處理過程自動負載均衡到多個CPU上。

 

相關文章