深入淺析Linux Perf 性能分析工具及火焰圖
Perf Event 子系統(tǒng)
Perf
?是內(nèi)置于 Linux 內(nèi)核源碼樹中的性能剖析(profiling)工具。它基于事件采樣的原理,以性能事件為基礎(chǔ),支持針對處理器相關(guān)性能指標(biāo)與操作系統(tǒng)相關(guān)性能指標(biāo)的性能剖析??捎糜谛阅芷款i的查找與熱點代碼的定位。
本文將詳細(xì)介紹 Linux Perf 的工作模式、Perf Events 的分類、Perf Tool 工具集以及火焰圖的相關(guān)內(nèi)容。
下圖展示了Perf的整體架構(gòu)。

Linux Perf 共由兩部分組成:
Perf Tools:用戶態(tài)的 Perf Tools 為用戶提供了一系列豐富的工具集用于收集、分析性能數(shù)據(jù)。
Perf Event Subsystem:Perf Event 子系統(tǒng)是內(nèi)核眾多子系統(tǒng)中的一員,其主要功能是和 Perf Tool 共同完成數(shù)據(jù)采集的工作。另外,Linux Hard Lockup Detector 也是通過 Perf Event 子系統(tǒng)來實現(xiàn)的。
Perf 工作模式
1. Couting Mode
Counting Mode 將會精確統(tǒng)計一段時間內(nèi) CPU 相關(guān)硬件計數(shù)器數(shù)值的變化。為了統(tǒng)計用戶感興趣的事件,Perf Tool 將設(shè)置性能控制相關(guān)的寄存器。這些寄存器的值將在監(jiān)控周期結(jié)束后被讀出。典型工具:Perf Stat。

2. Sampling Mode
Sampling Mode 將以定期采樣方式獲取性能數(shù)據(jù)。PMU 計數(shù)器將為某些特定事件配置溢出周期。當(dāng)計數(shù)器溢出時,相關(guān)數(shù)據(jù),如 IP、通用寄存器、EFLAG 將會被捕捉到。典型工具:Perf Record。


Perf Events分類

Couting 事件
Profiling 事件
Static Tracing 事件
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ? ?


Dynamic Tracing 事件
Perf Tool 工具集介紹
Perf Tool 是一個用戶態(tài)工具集,包含了 22 種子工具集,下表具體介紹每種工具的基本功能:


Perf List
Perf List:查看當(dāng)前軟硬件平臺支持的性能事件列表,性能事件的屬性。
u: 僅統(tǒng)計用戶空間程序觸發(fā)的性能事件
k: 僅統(tǒng)計內(nèi)核觸發(fā)的性能事件
h: 僅統(tǒng)計 Hypervisor 觸發(fā)的性能事件
G: 在 KVM 虛擬機(jī)中,僅統(tǒng)計 Guest 系統(tǒng)觸發(fā)的性能事件
H: 僅統(tǒng)計 Host 系統(tǒng)觸發(fā)的性能事件
p: 精度級別
Perf Stat
Perf Stat:分析性能。
Perf Top
Perf Top:實時顯示系統(tǒng)/進(jìn)程的性能統(tǒng)計信息, 默認(rèn)性能事件為 cycles ( CPU 周期數(shù) )。與 Linux top tool 功能類似。
Perf Record
Perf Record:記錄一段時間內(nèi)系統(tǒng)/進(jìn)程的性能事件, 默認(rèn)性能事件為 cycles ( CPU 周期數(shù) )。
Perf Script
讀取 Perf Record 結(jié)果。
Perf Script 輸出樣式
火焰圖
火焰圖是一種剖析軟件運(yùn)行狀態(tài)的工具,它能夠快速的將頻繁執(zhí)行的代碼路徑以圖式的形式展現(xiàn)給用戶。根據(jù) Brendan Gregg 先生的介紹,常用的火焰圖包括以下 5 種:
CPU
Memory
Off-CPU
Hot/Cold
Differential
本文只著重介紹了 CPU 和 Off-CPU 火焰圖,若讀者對另三種火焰圖感興趣可參看 Brendan Gregg 先生的博客。
CPU 火焰圖
CPU 火焰圖反映了一段時間內(nèi)用戶程序在 CPU 上運(yùn)行的熱點,其繪制原理是對 Perf 采集到的 samples 進(jìn)行解析,對函數(shù)調(diào)用棧進(jìn)行歸納合并,以柱狀圖的形式呈現(xiàn)給系統(tǒng)管理員。
圖片描述

每個長方塊代表了函數(shù)調(diào)用棧中的一個函數(shù),即為一層堆棧的內(nèi)容。Y 軸顯示堆棧的深度。頂層方塊表示 CPU 上正在運(yùn)行的函數(shù)。下面的函數(shù)即為它的祖先。X 軸的寬度代表被采集的 sample 的數(shù)量,越寬表示采集到的越多。
繪制原理
火焰圖的繪制需要 Perf Tool 以及一些 Perl 腳本的輔助。
采集樣本 通過 Perf Record 收集 CPU 熱點樣本原始文件。解析樣本 通過 Perf Script 解析樣本原始文件,得到樣本對應(yīng)的堆棧。繪制火焰圖 統(tǒng)計堆棧中函數(shù)出現(xiàn)的頻率,并以此繪制火焰圖。
Off-CPU 火焰圖
On CPU 火焰圖可反映某時刻 CPU 的運(yùn)行熱點,然而它卻留下了 Off-CPU 的問題:某些程序為何進(jìn)入睡眠狀態(tài)?睡眠時長有多久?
下圖是一張 Off-CPU 時間圖, 展示了一個由于系統(tǒng)調(diào)用而被阻塞的應(yīng)用線程的運(yùn)行情況。

從圖中我們可以看出應(yīng)用線程長時間被阻塞在 Off-CPU 狀態(tài),而這段時間則無法通過 On-CPU 火焰圖反映。
Brendan Gregg 共總結(jié)了 4 種類型的 Off-CPU 火焰圖:
1、I/O 火焰圖
File I/O 或 block device I/O 的時間消耗。


2、Off-CPU 火焰圖
分析線程睡眠路徑的火焰圖。

3、Wakeup 火焰圖
分析線程被阻塞源頭的火焰圖。

4、Chain 火焰圖
結(jié)合了 Off-CPU 和 Wakeup 火焰圖,詳細(xì)記錄了線程的睡眠原因及喚醒條件。注意:Chain 火焰圖性能開銷巨大,慎用!

Off-CPU 火焰圖繪制原理
通過 Off-CPU 火焰圖,我們可以輕松地了解系統(tǒng)中任何進(jìn)程的睡眠過程。其原理是利用 Perf Static Tracer 抓取一些進(jìn)程調(diào)度的相關(guān)事件,并利用 Perf Inject 將這些事件合并,最終得到誘發(fā)進(jìn)程睡眠的調(diào)用流程以及睡眠時間。
相關(guān) Tracepoints 介紹
1、sched : sched_switch
記錄了某進(jìn)程引發(fā)調(diào)度器調(diào)度的執(zhí)行流程,即產(chǎn)生進(jìn)程切換的原因。產(chǎn)生進(jìn)程切換的原因可能存在多種:
時間片耗盡
等待資源,如 I/O
等待鎖釋放
主動放棄 CPU
2、sched : sched_stat_sleep
由于主動放棄 CPU 而進(jìn)入睡眠的等待事件。它記錄了進(jìn)程處于睡眠狀態(tài)的時間。
3、sched : sched_stat_iowait
由于磁盤或網(wǎng)絡(luò) I/O 而引發(fā)的等待事件。它記錄了進(jìn)程因為等待 I/O 資源而進(jìn)入 D 狀態(tài)的時間。
4、sched : sched_stat_blocked
由于等待內(nèi)核鎖而引發(fā)的等待事件。它記錄了進(jìn)程等待鎖釋放而進(jìn)入 D 狀態(tài)的時間。
5、sched : sched_stat_wait
這個事件記錄了進(jìn)程在就緒隊列中等待執(zhí)行的時間。
實例介紹
下面這個例子介紹了如何統(tǒng)計系統(tǒng)中進(jìn)入 S 狀態(tài)的進(jìn)程的睡眠時長及原因。
通過追蹤 sched_switch 事件獲取相關(guān)進(jìn)程切換的調(diào)用棧;通過追蹤 sched_stat_sleep 事件獲取進(jìn)程的睡眠時間,最后利用 Perf Inject 合并兩個事件即可。下面我們看看合并的過程:
1、首先查看合并前的事件:
2、合并后的事件:
總結(jié)
本文首先介紹了 Linux Perf Event 子系統(tǒng)的整體架構(gòu),接著為讀者展示了 Perf 的兩種工作模式及各種類別的 Perf Events,之后詳細(xì)介紹了 Perf Tool 的多種子工具集,最后為讀者展示了 Bredan Gregg 先生引入的各種火焰圖及其繪制原理。通過閱讀本文,讀者將會對 Linux Perf 有更為深入的理解。
原文作者:滴滴云
