Perf 工具深度解析
Perf(Performance Counters for Linux)是 Linux 系統的性能分析工具,基于內核的 perf_event
子系統,通過硬件性能計數器(PMC)、軟件事件和跟蹤點(tracepoints)實現全方位性能監控。
一、工作原理與實現機制
1. 核心組件
組件 | 作用 |
---|---|
硬件性能計數器 | 利用 CPU 的 PMU(Performance Monitoring Unit)統計指令周期、緩存命中/失效等事件。 |
軟件事件 | 內核插樁統計上下文切換、缺頁異常等軟件行為(如 context-switches )。 |
跟蹤點 | 靜態內核探針(如 sched:sched_switch ),記錄特定代碼路徑的執行信息。 |
kprobes/uprobes | 動態內核/用戶空間探針,支持自定義函數級跟蹤。 |
2. 數據采集流程
+----------------+ +-------------------+ +-----------------+
| 配置事件 | ----> | perf_event_open() | ----> | 內核事件子系統 |
| (cycles, cache | | (系統調用) | | (PMU/軟件計數器) |
| misses, etc.) | +-------------------+ +-----------------+
+----------------+ |v
+------------------+ mmap() +--------------+
| 用戶空間工具 | <------------- | 環形緩沖區 |
| (perf record/stat)| | (存儲樣本) |
+------------------+ +--------------+
3. 關鍵機制
- 環形緩沖區:采樣數據通過無鎖環形緩沖(避免系統調用開銷)傳遞到用戶空間。
- 采樣模式:
- 計數模式:累計事件發生次數(
perf stat
)。 - 中斷采樣:事件達到閾值時觸發中斷,記錄指令指針/IP(
perf record
)。
- 計數模式:累計事件發生次數(
- 符號解析:通過
/proc/kallsyms
或 ELF 文件將地址映射為函數名。
二、命令大全與使用示例
1. 常用命令總結
命令 | 功能 | 常用選項 |
---|---|---|
perf stat | 統計事件發生的絕對次數 | -e (指定事件), -p (PID), -a (全局) |
perf record | 采樣并保存數據到 perf.data | -g (調用棧), -F (采樣頻率), -o (輸出文件) |
perf report | 解析 perf.data 生成報告 | --stdio (文本報告), -n (顯示樣本數) |
perf top | 實時顯示熱點函數 | -e (事件), -K (隱藏內核符號) |
perf list | 列出支持的事件 | --details (顯示事件詳情) |
perf script | 導出采樣數據為腳本格式 | -i (輸入文件), -F (自定義字段) |
perf trace | 類似 strace ,跟蹤系統調用 | -p (PID), -e (過濾系統調用) |
perf annotate | 匯編代碼級注解 | --stdio (文本模式), -s (符號) |
2. 詳細示例
Perf 典型使用場景及命令詳解
2.1 CPU 性能分析
場景 | 命令示例 | 說明 |
---|---|---|
CPU 熱點函數分析 | perf top -e cycles -p <PID> | 實時查看進程的熱點函數 |
調用鏈分析 | perf record -F 99 -g -p <PID> -o perf.data; perf report --stdio | 記錄調用棧并生成文本報告 |
多核負載均衡分析 | perf stat -e sched:sched_migrate_task -a sleep 10 | 監控任務在 CPU 核間的遷移情況 |
IPC 指標分析 | perf stat -e cycles,instructions -p <PID> -- sleep 5 | 計算指令/周期比 (IPC = instructions/cycles) |
示例:CPU 瓶頸診斷
# 1. 查找 CPU 占用最高的進程
perf top# 2. 對高負載進程 (PID 1234) 進行采樣
perf record -F 997 -g -p 1234 -o cpu_hotspot.data -- sleep 30# 3. 生成帶調用棧的報告
perf report -i cpu_hotspot.data --stdio --no-children
輸出片段:
# Overhead Command Shared Object Symbol
# ........ ....... ................ ................................
#62.15% nginx nginx [.] ngx_http_process_request|---ngx_http_process_request| |--45.32%-- ngx_http_core_content_phase| ngx_http_proxy_handler| || |--38.71%-- ngx_http_upstream_connect| | __connect
2.2 內存子系統分析
場景 | 命令示例 | 說明 |
---|---|---|
緩存命中率分析 | perf stat -e cache-references,cache-misses <command> | 統計 L1/L2/L3 緩存效率 |
內存帶寬分析 | perf stat -e uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ | 監控 DDR 內存讀寫帶寬 (需 Intel PMU) |
缺頁異常分析 | perf stat -e page-faults,minor-faults,major-faults -p <PID> | 區分次/主缺頁異常 |
示例:內存敏感型應用優化
# 1. 檢測緩存效率
perf stat -e \L1-dcache-load-misses,LLC-load-misses,dTLB-load-misses \./memory_intensive_app# 2. 輸出結果35,421,632 L1-dcache-load-misses # 12.45% of all L1-dcache hits 8,765,432 LLC-load-misses # 3.21% of all LL-cache hits1,234,567 dTLB-load-misses # 0.45% of all dTLB cache hits
2.3 I/O 性能分析
場景 | 命令示例 | 說明 |
---|---|---|
塊設備 I/O 延遲 | perf record -e block:block_rq_issue,block:block_rq_complete -a | 跟蹤塊設備請求生命周期 |
文件系統操作跟蹤 | perf record -e ext4:*,xfs:* -a | 捕獲特定文件系統事件 |
系統調用分析 | perf trace -e 'read,write,openat' -p <PID> | 監控文件相關系統調用 |
示例:磁盤 I/O 瓶頸診斷
# 1. 跟蹤塊設備事件
perf record -e block:block_rq_issue -e block:block_rq_complete -a# 2. 生成延遲報告
perf script | awk '/block_rq_issue/{ts[$5]=$4}/block_rq_complete/{if(ts[$5])printf "%.2f ms\n", ($4-ts[$5])*1000}'
輸出:
8.23 ms # I/O 請求延遲
12.45 ms
5.67 ms
2.4 網絡性能分析
場景 | 命令示例 | 說明 |
---|---|---|
網絡協議棧跟蹤 | perf record -e skb:kfree_skb -e net:net_dev_xmit -a | 監控丟包和發送事件 |
TCP 函數跟蹤 | perf probe --add tcp_v4_connect; perf record -e probe:tcp_v4_connect | 動態跟蹤 TCP 連接建立 |
網絡延遲分析 | perf trace -e sendto,recvfrom -p <PID> -T | 跟蹤網絡收發系統調用時間戳 |
示例:網絡丟包分析
# 1. 創建丟包檢測探針
sudo perf probe --add 'kfree_skb reason'# 2. 記錄丟包事件
sudo perf record -e probe:kfree_skb -aR -o net_drop.data# 3. 分析丟包原因
sudo perf script -i net_drop.data | awk '{print $5}' | sort | uniq -c | sort -nr
輸出:
1423 TCP: Too many orphaned sockets890 NETDEV WATCHDOG: enp0s3 transmit timeout321 ICMP: Destination unreachable
2.5 鎖與同步分析
場景 | 命令示例 | 說明 |
---|---|---|
鎖競爭分析 | perf record -e lock:lock_acquire -e lock:lock_release -g -p <PID> | 跟蹤鎖獲取/釋放事件 |
調度延遲分析 | perf sched record -p <PID>; perf sched latency | 分析任務調度延遲 |
中斷分析 | perf record -e irq:irq_handler_entry -e irq:irq_handler_exit -a | 跟蹤中斷處理時間 |
示例:鎖競爭診斷
# 1. 記錄鎖事件
perf record -e lock:lock_acquire -e lock:lock_release -g -p 5678 -o locks.data# 2. 生成競爭報告
perf lock report -i locks.data --combine-locks --sort contended
輸出:
Name acquired contended avg wait (ns)
----------------------------------------------------------
&sb->s_type->i_lock 14235 4231 15234&rq->lock 8765 2109 8765mm->page_table_lock 6543 987 5432
2.6 火焰圖生成
perf record -F 99 -a -g -- sleep 30
perf script > out.perf
./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
./FlameGraph/flamegraph.pl out.folded > flame.svg
2.7 Perf 工作流程圖
2.8 高級技巧
-
PEBS 精確采樣
perf record -e cycles:pp -c 1000000 -p <PID> # 每100萬周期采樣一次
-
事件分組統計
perf stat -e '{cycles,instructions,branch-misses}' -r 5 ./program
-
時間戳跟蹤
perf record -e sched:sched_switch -T -a -- sleep 10 perf script --ns
-
跨進程跟蹤
perf record -e 'sched:sched_wakeup,sched:sched_switch' -a
-
用戶空間探針
perf probe -x /path/to/bin 'func_name' perf record -e probe_bin:func_name -a
三、Perf 使用流程圖
四、高級技巧
- 事件修飾符:
u
:僅用戶空間,如perf stat -e cycles:u
k
:僅內核空間
- 精確采樣:
perf record -e cycles:pp -p 1234 # 使用 PEBS 精確采樣
- 多事件分析:
perf stat -e cycles,instructions,cache-references,cache-misses ls
五、注意事項
- 權限要求:部分事件需要
CAP_PERFMON
或root
權限。 - 符號表:用戶程序需編譯時添加
-g
選項(保留調試符號)。 - 內核版本:不同內核版本支持事件可能不同(
perf list
查看)。
通過靈活組合命令,Perf 可定位 CPU 瓶頸、內存延遲、I/O 問題等,是 Linux 性能調優的核心工具。