11.如何迅速分析出系統CPU的瓶頸在哪裏
前幾節裏,通過幾個案例,分析了各種常見的 CPU 性能問題。通過這些,相信對 CPU 的性能分析已經不再陌生和恐懼,起碼有了基本的思路,也了解了不少 CPU 性能的分析工 具。
不過,我猜你可能也碰到了一個我曾有過的困惑: CPU 的性能指標那麽多,CPU 性能分析工具 也是一抓一大把,如果離開專欄,換成實際的工作場景,我又該觀察什麽指標、選擇哪個性能工 具呢?
不要擔心,今天我就以多年的性能優化經驗,給你總結出一個“又快又準”的瓶頸定位套路,告 訴你在不同場景下,指標工具怎麽選,性能瓶頸怎麽找。
CPU 性能指標
我們先來回顧下,描述 CPU 的性能指標都有哪些。你可以自己先找張紙,憑著記憶寫一寫;或 者打開前面的文章,自己總結一下。
首先,最容易想到的應該是 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 時 間百分比。
第二個比較容易想到的,應該是平均負載(Load Average),也就是系統的平均活躍進程數。 它反應了系統的整體負載情況,主要包括三個數值,分別指過去 1 分鐘、過去 5 分鐘和過去 15 分鐘的平均負載。
理想情況下,平均負載等於邏輯 CPU 個數,這表示每個 CPU 都恰好被充分利用。如果平均負 載大於邏輯 CPU 個數,就表示負載比較重了。
第三個,也是在專欄學習前你估計不太會註意到的,進程上下文切換,包括:
- 無法獲取資源而導致的自願上下文切換;
- 被系統強制調度導致的非自願上下文切換。
上下文切換,本身是保證 Linux 正常運行的一項核心功能。但過多的上下文切換,會將原本運 行進程的 CPU 時間,消耗在寄存器、內核棧以及虛擬內存等數據的保存和恢復上,縮短進程真 正運行的時間,成為性能瓶頸。
除了上面幾種,還有一個指標,CPU 緩存的命中率。由於 CPU 發展的速度遠快於內存的發展, CPU 的處理速度就比內存的訪問速度快得多。這樣,CPU 在訪問內存的時候,免不了要等待內 存的響應。為了協調這兩者巨大的性能差距,CPU 緩存(通常是多級緩存)就出現了。
就像上面這張圖顯示的,CPU 緩存的速度介於 CPU 和內存之間,緩存的是熱點的內存數據。根 據不斷增長的熱點數據,這些緩存按照大小不同分為 L1、L2、L3 等三級緩存,其中 L1 和 L2 常用在單核中, L3 則用在多核中。
從 L1 到 L3,三級緩存的大小依次增大,相應的,性能依次降低(當然比內存還是好得多)。 而它們的命中率,衡量的是 CPU 緩存的復用情況,命中率越高,則表示性能越好。
這些指標都很有用,需要我們熟練掌握,所以我總結成了一張圖,幫你分類和記憶。你可以保存 打印下來,隨時查看復習,也可以當成 CPU 性能分析的“指標篩選”清單。
性能工具
掌握了 CPU 的性能指標,我們還需要知道,怎樣去獲取這些指標,也就是工具的使用。
你還記得前面案例都用了哪些工具嗎?這裏我們也一起回顧一下 CPU 性能工具。
首先,平均負載的案例。我們先用 uptime, 查看了系統的平均負載;而在平均負載升高後,又 用 mpstat 和 pidstat ,分別觀察了每個 CPU 和每個進程 CPU 的使用情況,進而找出了導致平 均負載升高的進程,也就是我們的壓測工具 stress。
第二個,上下文切換的案例。我們先用 vmstat ,查看了系統的上下文切換次數和中斷次數;然 後通過 pidstat ,觀察了進程的自願上下文切換和非自願上下文切換情況;最後通過 pidstat , 觀察了線程的上下文切換情況,找出了上下文切換次數增多的根源,也就是我們的基準測試工具 sysbench。
第三個,進程 CPU 使用率升高的案例。我們先用 top ,查看了系統和進程的 CPU 使用情況, 發現 CPU 使用率升高的進程是 php-fpm;再用 perf top ,觀察 php-fpm 的調用鏈,最終找 出 CPU 升高的根源,也就是庫函數 sqrt() 。
第四個,系統的 CPU 使用率升高的案例。我們先用 top 觀察到了系統 CPU 升高,但通過 top 和 pidstat ,卻找不出高 CPU 使用率的進程。於是,我們重新審視 top 的輸出,又從 CPU 使 用率不高但處於 Running 狀態的進程入手,找出了可疑之處,最終通過 perf record 和 perf report ,發現原來是短時進程在搗鬼。
另外,對於短時進程,我還介紹了一個專門的工具 execsnoop,它可以實時監控進程調用的外 部命令。
第五個,不可中斷進程和僵屍進程的案例。我們先用 top 觀察到了 iowait 升高的問題,並發現 了大量的不可中斷進程和僵屍進程;接著我們用 dstat 發現是這是由磁盤讀導致的,於是又通過 pidstat 找出了相關的進程。但我們用 strace 查看進程系統調用卻失敗了,最終還是用 perf 分 析進程調用鏈,才發現根源在於磁盤直接 I/O 。
最後一個,軟中斷的案例。我們通過 top 觀察到,系統的軟中斷 CPU 使用率升高;接著查看 /proc/softirqs, 找到了幾種變化速率較快的軟中斷;然後通過 sar 命令,發現是網絡小包的問 題,最後再用 tcpdump ,找出網絡幀的類型和來源,確定是一個 SYN FLOOD 攻擊導致的。
到這裏,估計你已經暈了吧,原來短短幾個案例,我們已經用過十幾種 CPU 性能工具了,而且 每種工具的適用場景還不同呢!這麽多的工具要怎麽區分呢?在實際的性能分析中,又該怎麽選 擇呢?
我的經驗是,從兩個不同的維度來理解它們,做到活學活用。
活學活用,把性能指標和性能工具聯系起來
第一個維度,從 CPU 的性能指標出發。也就是說,當你要查看某個性能指標時,要清楚知道哪 些工具可以做到。
根據不同的性能指標,對提供指標的性能工具進行分類和理解。這樣,在實際排查性能問題時, 你就可以清楚知道,什麽工具可以提供你想要的指標,而不是毫無根據地挨個嘗試,撞運氣。
其實,我在前面的案例中已經多次用到了這個思路。比如用 top 發現了軟中斷 CPU 使用率高 後,下一步自然就想知道具體的軟中斷類型。那在哪裏可以觀察各類軟中斷的運行情況呢?當然 是 proc 文件系統中的 /proc/softirqs 這個文件。
緊接著,比如說,我們找到的軟中斷類型是網絡接收,那就要繼續往網絡接收方向思考。系統的 網絡接收情況是什麽樣的?什麽工具可以查到網絡接收情況呢?在我們案例中,用的正是雖然你不需要把所有工具背下來,但如果能理解每個指標對應的工具的特性,一定更高效、更靈 活地使用。這裏,我把提供 CPU 性能指標的工具做成了一個表格,方便你梳理關系和理解記 憶,當然,你也可以當成一個“指標工具”指南來使用。
下面,我們再來看第二個維度。
第二個維度,從工具出發。也就是當你已經安裝了某個工具後,要知道這個工具能提供哪些指 標。
這在實際環境特別是生產環境中也是非常重要的,因為很多情況下,你並沒有權限安裝新的工具 包,只能最大化地利用好系統中已經安裝好的工具,這就需要你對它們有足夠的了解。
具體到每個工具的使用方法,一般都支持豐富的配置選項。不過不用擔心,這些配置選項並不用 背下來。你只要知道有哪些工具、以及這些工具的基本功能是什麽就夠了。真正要用到的時候, 通過 man 命令,查它們的使用手冊就可以了。
同樣的,我也將這些常用工具匯總成了一個表格,方便你區分和理解,自然,你也可以當成一 個“工具指標”指南使用,需要時查表即可。
如何迅速分析 CPU 的性能瓶頸
我相信到這一步,你對 CPU 的性能指標已經非常熟悉,也清楚每種性能指標分別能用什麽工具 來獲取。
那是不是說,每次碰到 CPU 的性能問題,你都要把上面這些工具全跑一遍,然後再把所有的 CPU 性能指標全分析一遍呢?
你估計覺得這種簡單查找的方式,就像是在傻找。不過,別笑話,因為最早的時候我就是這麽做 的。把所有的指標都查出來再統一分析,當然是可以的,也很可能找到系統的潛在瓶頸。
但是這種方法的效率真的太低了!耗時耗力不說,在龐大的指標體系面前,你一不小心可能就忽 略了某個細節,導致白幹一場。我就吃過好多次這樣的苦。
所以,在實際生產環境中,我們通常都希望盡可能快地定位系統的瓶頸,然後盡可能快地優化性 能,也就是要又快又準地解決性能問題。
那有沒有什麽方法,可以又快又準找出系統瓶頸呢?答案是肯定的。
雖然 CPU 的性能指標比較多,但要知道,既然都是描述系統的 CPU 性能,它們就不會是完全 孤立的,很多指標間都有一定的關聯。想弄清楚性能指標的關聯性,就要通曉每種性能指標的工 作原理。這也是為什麽我在介紹每個性能指標時,都要穿插講解相關的系統原理,希望你能記住 這一點。
舉個例子,用戶 CPU 使用率高,我們應該去排查進程的用戶態而不是內核態。因為用戶 CPU 使用率反映的就是用戶態的 CPU 使用情況,而內核態的 CPU 使用情況只會反映到系統 CPU 使 用率上。
你看,有這樣的基本認識,我們就可以縮小排查的範圍,省時省力。
所以,為了縮小排查範圍,我通常會先運行幾個支持指標較多的工具,如 top、vmstat 和 pidstat 。為什麽是這三個工具呢?仔細看看下面這張圖,你就清楚了。
這張圖裏,我列出了 top、vmstat 和 pidstat 分別提供的重要的 CPU 指標,並用虛線表示關聯 關系,對應出了性能分析下一步的方向。
通過這張圖你可以發現,這三個命令,幾乎包含了所有重要的 CPU 性能指標,比如:
- 從 top 的輸出可以得到各種 CPU 使用率以及僵屍進程和平均負載等信息。
- 從 vmstat 的輸出可以得到上下文切換次數、中斷次數、運行狀態和不可中斷狀態的進程 數。
- 從 pidstat 的輸出可以得到進程的用戶 CPU 使用率、系統 CPU 使用率、以及自願上下文切 換和非自願上下文切換情況。
另外,這三個工具輸出的很多指標是相互關聯的,所以,我也用虛線表示了它們的關聯關系,舉 幾個例子你可能會更容易理解。
第一個例子,pidstat 輸出的進程用戶 CPU 使用率升高,會導致 top 輸出的用戶 CPU 使用率 升高。所以,當發現 top 輸出的用戶 CPU 使用率有問題時,可以跟 pidstat 的輸出做對比,觀 察是否是某個進程導致的問題。
而找出導致性能問題的進程後,就要用進程分析工具來分析進程的行為,比如使用 strace 分析
系統調用情況,以及使用 perf 分析調用鏈中各級函數的執行情況。
第二個例子,top 輸出的平均負載升高,可以跟 vmstat 輸出的運行狀態和不可中斷狀態的進程 數做對比,觀察是哪種進程導致的負載升高。
- 如果是不可中斷進程數增多了,那麽就需要做 I/O 的分析,也就是用 dstat 或 sar 等工具, 進一步分析 I/O 的情況。
- 如果是運行狀態進程數增多了,那就需要回到 top 和 pidstat,找出這些處於運行狀態的到 底是什麽進程,然後再用進程分析工具,做進一步分析。
最後一個例子,當發現 top 輸出的軟中斷 CPU 使用率升高時,可以查看 /proc/softirqs 文件中 各種類型軟中斷的變化情況,確定到底是哪種軟中斷出的問題。比如,發現是網絡接收中斷導致 的問題,那就可以繼續用網絡分析工具 sar 和 tcpdump 來分析。
註意,我在這個圖中只列出了最核心的幾個性能工具,並沒有列出所有。這麽做,一方面是不想 用大量的工具列表嚇到你。在學習之初就接觸所有或核心或小眾的工具,不見得是好事。另一方 面,是希望你能先把重心放在核心工具上,畢竟熟練掌握它們,就可以解決大多數問題。
所以,你可以保存下這張圖,作為 CPU 性能分析的思路圖譜。從最核心的這幾個工具開始,通 過我提供的那些案例,自己在真實環境裏實踐,拿下它們。 小結 今天,我帶你回憶了常見的 CPU 性能指標,梳理了常見的 CPU 性能觀測工具,最後還總結了 快速分析 CPU 性能問題的思路。 雖然 CPU 的性能指標很多,相應的性能分析工具也很多,但熟悉了各種指標的含義之後,你就 會發現它們其實都有一定的關聯。順著這個思路,掌握常用的分析套路並不難。
11.如何迅速分析出系統CPU的瓶頸在哪裏