1. 小聲BIBI
事情的起因是在線上碰到了一次CPU使用率標高導致系統異常,當時使用sar -u命令查看發現system(內核態)數值飆高至40%左右,明顯大於平時,此時就需使用perf命令進行性能分析,查找出是哪個服務或進程導致的內存飆高。本文不會介紹perf的實現原理等核心內容,僅做簡單的命令介紹。
2. 前期準備
一般我們的機器是沒有安裝perf的,執行命令:yum install perf -y安裝perf,若出現下載較慢的情況,可以百度linux修改yum源爲阿里雲。
3. 正餐開始
3.1. perf list
首先我們一定會好奇的是perf究竟能監控些什麼,我們可以使用perf list命令查看perf所能監控到的性能指標。
可以看到有許多的CPU事件,雖然到現在我查看的資料中沒有一個能夠將所有事件都解釋的很清楚,但是我們平時常見的並不多。整體上分爲了三類,Software event,Hardware cache event,Kernel PMU event。
- Software Event 是內核軟件產生的事件,比如進程切換,tick 數等 ;
- Hardware cache event是由 PMU 硬件產生的事件,比如 cache 命中,當您需要了解程序對硬件特性的使用情況時,便需要對這些事件進行採樣;
- Tracepoint event 是內核中的靜態 tracepoint 所觸發的事件,這些 tracepoint 用來判斷程序運行期間內核的行爲細節,比如 slab 分配器的分配次數等。
3.2. perf stat
知道了CPU有哪些性能事件後,我們需要先關注CPU的整體情況,這時perf stat命令恰巧能滿足我們的需求。
常用參數:-p: 根據指定進程的pid對該進程進行監控
perf stat執行效果如下:
截圖中是對進程號爲2812的進程CPU使用率進行監控,首先看到最下面一行的time elapsed,這裏輸出的是監控總時長。
下面對輸出的參數做簡要說明:
task-clock:監控時間內程序佔用CPU的時間,單位是毫秒。
CPUs utilized:CPU使用率,CPUs utilized= task-clock/(time elapsed*1000)
context-switches:程序在運行過程中發生的上下文切換次數。
cpu-migrations:程序在運行過程中發生的CPU遷移次數,即被調度器從一個CPU轉移到另外一個CPU上運行。
page-faults:缺頁。指當內存訪問時先根據進程虛擬地址空間中的虛擬地址通過MMU查找該內存頁在物理內存的映射,沒有找到該映射,則發生缺頁,然後通過CPU中斷調用處理函數,從物理內存中讀取。
cycles:CPU時鐘週期(我截圖中的虛擬機不支持)。說到CPU時鐘週期就要簡單的講下指令,CPU回到指令集中選取指令執行,一個指令包含5個步驟:讀取指令,指令解碼,執行,內存訪問,寄存區回寫。每個步驟的執行至少都需要一個CPU的時鐘週期,CPU中有一個叫功能單元的組件負責處理每個步驟。
Instructions:該進程在這段時間內完成的CPU指令(我截圖中的虛擬機不支持)。在網上看到還會有一個重要的相關指標:insns per cycle,表示一個時鐘週期內能完成多少個CPU指令。該值越高,表示CPU的性能越好。
branches:這段時間內發生分支預測的次數。比如我們有一個簡單的if判斷,有10次都是走的true分支,CPU會優先預測後續走的都是true
branches-misses:這段時間內分支預測失敗的次數,這個值越小越好。
3.3. perf top
perf stat固然能整體的看到CPU的狀態,但是卻不能告訴我們到底是我們程序的什麼方法導致CPU異常,perf top命令恰巧能滿足我們這個需求,perf top命令與我們平時使用的top命令類似,可以實時查看當前系統進程函數佔用率整體情況,在這種時候就滿足我們所需要的第一感受。
執行效果如下:
可以看到圖中第一行有三個關鍵字,採樣數:Samples,事件:event,事件數量:Event count,所以第一行的意思是cpu-clock事件的數量爲6K,總事件數爲53840912。
再看第二行,第二行其實是下面表格的表頭,參數意義如下:
Overhead |
該Symbol 的性能事件佔所有采樣事件中的比例 |
---|---|
Shared |
該Symbol所在的動態共享對象(Dynamic Shared Object),如內核、進程名、動態鏈接庫名、內核模塊名等 |
Object |
是動態共享對象的類型。 [.]:表示用戶空間的可執行程序、或者動態鏈接庫 [k]:表示內核空間。 |
Symbol |
符號名,也是函數名。當函數名未知時,用十六進制的地址來表示 |
拿圖中示例解析,我們可以看到_raw_spin_unlock_irqrestore的函數佔用最多,爲17.65%。共享對象爲kernel,類型爲內核空間。
perf top我經常常用的參數是-p [pid]和-g,因爲大部分時間都是我們自己的代碼導致cpu使用異常,所以我們可以先使用ps -ef|grep [進程名]來查找出我們進程的PID,然後使用perf top -p [pid]的命令來查看具體是哪個函數佔用性能較高。而-g參數可以打印出具體的函數調用關係,這個對我們做具體的函數優化很有必要,這個參數有助於我們定位到到底是程序的那個函數佔用CPU較高。
3.4. perf record和perf report
使用perf top我們只能看到當時的情況,且不能留存,大部分事件我們可能需要統計一段時間的CPU情況,這時候perf record就是不二利器,常用用法:perf record -ag -p [PID],回車執行後監控一段時間,然後按CTRL+C會自動生成一個perf.data的報告文件,若想修改輸出文件名,可以使用-o參數,例如: perf record -ago 20200603.data -p 3051,然後使用perf report -i 20200603.data來分析輸出報告。
因爲輸出內容與perf top一樣,限於篇幅,這裏不做贅述。