Linux性能優化實戰CPU篇(一)


一、優化方向

1,性能指標

  從應用負載的視角出發,考慮“吞吐”和“延時”

  從系統資源的視角出發,考慮資源使用率、飽和度等

  

2,性能優化步驟

  • 選擇指標評估應用程序和系統的性能;
  • 為應用程序和系統設置性能目標;
  • 進行性能基准測試;
  • 性能分析定位瓶頸;
  • 優化系統和應用程序;
  • 性能監控和告警。

3,Linux性能工具圖譜

二、平均負載

1,stress

安裝命令:apt install stress
  stress 是一個linux系統壓力測試工具,這里我們用作異常進程模擬平均負載升高場景
#模擬一個CPU使用率 100%  stress -c N 會讓stress生成N個工作進程進行開方運算,以此對CPU產生負載。
stress --cpu 1 --timeout 600
#模擬I/O密集進程 stress -i N  會產生N個進程,每個進程反復調用sync()將內存上的內容寫到硬盤上, --timeout 600 表示600秒后退出 stress -i 1 --timeout 600

2,sysstat

安裝命令:apt install sysstat
sysstat 是一個常用的linux性能工具,用來監控和分析系統的性能。
  • mpstat 是一個常用的多核cpu性能分析工具,用來實時查看每個CPU的性能指標,以及所有CPU的平均指標 
  • mpstat -P ALL 5   
    其中-P ALL  表示監控所有CPU
    數字5,表示每間隔5秒輸出一組數據
  • pidstat 是一個常用的進程性能分析工具,用來實時查看進程的CPU、內存、IO以及上下文切換等性能指標
  • pidstat -u 5 1
    每間隔5秒輸出一組數據

  pid參數詳解  

-u:默認的參數,顯示各個進程的cpu使用統計
-r:顯示各個進程的內存使用統計
-d:顯示各個進程的IO使用情況
-p:指定進程號
-w:顯示每個進程的上下文切換情況
-t:顯示選擇任務的線程的統計信息外的額外信息
-T { TASK | CHILD | ALL }
這個選項指定了pidstat監控的。TASK表示報告獨立的task,CHILD關鍵字表示報告進程下所有線程統計信息。ALL表示報告獨立的task和task下面的所有線程。
注意:task和子線程的全局的統計信息和pidstat選項無關。這些統計信息不會對應到當前的統計間隔,這些統計信息只有在子線程kill或者完成的時候才會被收集。
-V:版本號
-h:在一行上顯示了所有活動,這樣其他程序可以容易解析。
-I:在SMP環境,表示任務的CPU使用率/內核數量
-l:顯示命令名和所有參數

3,場景模擬

a>CPU密集

  stress

#模擬一個CPU使用率 100%  stress -c N 會讓stress生成N個工作進程進行開方運算,以此對CPU產生負載。--timeout 600 表示600秒后退出 
stress --cpu 1 --timeout 600

  監控uptime,負載在升高

  mpstat,發現一個CPU的使用率高達100%,但是iowait為0,說明平均負載的升高由於CPU的使用率為100%

   pidstat,發現是stress進程導致CPU使用率升高

 

b>I/O密集

  stress

#模擬I/O密集進程  stress -i N  會產生N個進程,每個進程反復調用sync()將內存上的內容寫到硬盤上
stress -i 1 --timeout 600

  監控uptime,負載在升高

  mpstat,發現一個系統CPU使用率升至23.87%,iowait高達67.53% 。說明平均負載的升高由於iowait的升高

  

  

  pidstat,發現是由於stress進程導致

c>大量進程的場景

  stress

stress -c 8 --timeout 600

  uptime

  pidstat,發現8個進程在爭搶2個CPU,每個進程等待CPU的時間高達75%,導致CPU過載

三、CPU的上下文切換

1,基本概念

  CPU寄存器:CPU內置的容量小、但速度極快的內存

  程序計數器:用於存儲CPU正在執行的指令位置、或者即將執行的下一條指令位置

  CPU上下文:CPU寄存器和程序計數器所必須的依賴環境

  CPU上下文切換:先把前一個任務的CPU上下文(也就是CPU寄存器和程序計數器)保存起來,然后加載新任務的上下文到這些寄存器和程序計數器,最后再跳轉到程序計數器所指的新位置,運行新任務。

2,分類

a>進程上下文切換

  Linux按照特權等級,把進程的運行空間分為內核空間和用戶空間,分別對應CPU特權等級的 Ring 0 和Ring 3

  • 內核空間(Ring 0)具有最高權限,可以直接訪問所有資源
  • 用戶空間(Ring 3)只能訪問受限資源,不能直接訪問內存等硬件設備,必須通過系統調用陷入內核中,才能訪問這些特權資源

  

  換個角度,也就是進程既可以在用戶空間運行,又可以在內核空間運行。進程在用戶空間運行時,被稱為進程的用戶態,而陷入內核空間的時候,被稱為進程的內核態。

  在進程切換時才需要切換上下文,也就是進程調度時。Linux為每個CPU都維護了一個就緒隊列,將活躍進程按照優先級和等待CPU的時間排序,然后選擇最需要CPU的進程,也就是優先級最高和等待CPU時間最長的進程運行。涉及到的場景包括:

  • 為了保證所有進程可以得到公平調度,CPU時間被划分為一段段的時間片,這些時間片再被輪流分配給各個進程。這樣,當某個進程的時間片耗盡了,就會被系統掛起,切換到其他正在等待CPU的進程運行
  • 進程在系統資源不足(比如內存不足)時,要等到資源滿足后才可以運行,這個時候進程也會被掛起,並有系統調度其他進程運行
  • 當進程通過睡眠函數sleep這樣的方法將自己主動掛起時,自然也會重新調度
  • 當有優先級更高的進程運行時,為了保證高優先級進程的運行,當前進程會被掛起,由高優先級進程來運行
  • 當發生硬件中斷時,CPU上的進程會被中斷掛起,轉而執行內核中的中斷服務進程

b>線程上下文切換

  線程是調度的基本單位,而進程則是資源擁有的基本單位

  • 當進程只有一個線程時,可以認為進程就等於線程
  • 當進程擁有多個線程時,這些線程會共享相同的虛擬內存和全局變量等資源。這些資源在上下文切換時不需要修改
  • 線程也有自己的私有數據,比如棧和寄存器,這些在上下文切換時也需要保存

  線程上下文切換:1,前后兩個線程屬於不同進程,由於資源不同就是進程上下文切換;2,前后兩個線程屬於同一個進程,此時虛擬內存共享,切換時只需要切換線程的私有數據、寄存器等不共享的數據。

c>中斷上下文切換

  • 為了快速響應硬件的事件,中斷處理會打斷進程的正常調度和執行,轉而調用中斷處理程序,響應設備事件。而在打斷其他進程時,就需要將進程當前的狀態保存起來,這樣在中斷結束后,進程仍然可以從原來的狀態恢復運行
  • 與進程上下文切換不同,中斷上下文切換並不涉及進程的用戶態。所以,即便中斷過程打斷了一個正處在用戶態的進程,也不需要保存和恢復這個進程的虛擬內存、全局變量等用戶態資源。中斷上下文,其實只包括內核態中斷服務程序執行所必需的狀態,包括CPU寄存器、內核堆棧、硬件中斷參數等

3,CPU上下文切換實戰

a>vmstat

  

  • cs(context switch)是每秒上下文切換的次數
  • in(interrupt)是每秒中斷的次數
  • r(Running or Runnable)是就緒隊列的長度,也就是正在運行和等待的CPU的進程數
  • b(Blocked)是處於不可中斷睡眠狀態的進程數

b>pidstat

  vmstat只給出了系統總體的上下文切換情況,要想查看每個進程的詳細情況,就需要使用我們pidstat。加上-w選項,則可以查看每個進程上下文切換的情況

  

  • cswch(voluntary context switches),每秒自願上下文切換次數。指進程無法獲取所需要資源,導致的上下文切換。比如:I/O、內存等系統資源不足時,就會發生自願上下文切換。
  • nvcswch(non voluntary context switches),每秒非自願上下文切換。指進程由於時間片已到等原因,被系統強制調度,進程發生的上下文切換。比如:大量進程都在爭搶CPU時,就容易發生非自願上下文切換。

c>案例實操

  查看系統的上下文切換次數 

 

   采用sysbench進行壓測

  

  再次查看vmstat

  

   發現cs列的上下文切換數量從之前的35驟然上升到了139萬多。同時,r列:就緒隊列的長度為8,遠超CPU的個數2,所以判定有大量的CPU競爭;us(user)和sy(system)列:這兩列的CPU使用率加起來上升到了100%,其中系統CPU使用率,也就是sy列高達84%,說明CPU主要是被內核占用了;in列:中斷次數也上升到1萬左右,說明中斷處理也是個潛在的問題。綜合這幾個指標,系統的就緒隊列過長,也就是正在運行和等待CPU的進程數過多,導致大量的上下文切換,而上下文切換又導致系統的CPU的占用率升高。

  采用pidstat分析

  

  

  • CPU使用率升高果然是sysbench導致的,已達100%
  • 非自願上下文切換最高的為pidstat,自願上下文切換頻率最高的線程為kworker和sshd
  • 問題:pidstat輸出的上線文切換明顯小於vmstat輸出的上下文切換。采用man pidstat 發現,pidstat默認顯示進程的指標數據,加上-t參數后,才會輸出線程指標

  

  結合兩次的pidstat可以看出,sysbench(主線程)的上下文切換次數看起來並不太多,但它的子線程的上下文切換次數卻很多。

  采用watch觀察interrupts中斷

  

  觀察發現,變化速度最快的是重調度中斷(RES),表示喚醒空閑狀態的CPU來調度新的任務運行。這是多處理器系統(SMP)中,調度器用來分散任務到不同CPU的機制,通常也被稱為處理器間中斷(Inter-Processor Interrupts, IPI)。

d>總結

  如果系統的上下文切換次數比較穩定,那么從數百到一萬內,都應該算是正常的。當上下文切換次數超過一萬次,或者切換次數出現數量級的增長時,都很可能已經出現了性能問題:

  • 自願上下文切換變多,說明進程都在等待資源,有可能發生了I/O等其他問題
  • 非自願上下文切換變多,說明進程都在被強制調度,也就是都在爭搶CPU,說明CPU的確成了瓶頸
  • 中斷次數變多了,說明CPU被中斷處理程序占用,需要查看/proc/interrupts文件來分析具體的中斷類型

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM