高延遲的 2 個場景,觸發(fā) perf 錄包思路
?當(dāng)前 perf 沒有常駐內(nèi)存,后續(xù)提供 perf 常駐內(nèi)存功能。且 perf 啟動需要 0.5~1s,所以,存在 2 個場景
1.頻繁連續(xù)高延遲(復(fù)現(xiàn)后的幾秒內(nèi),繼續(xù)頻繁復(fù)現(xiàn)):可以配置自動觸發(fā)工具,自動觸發(fā) perf trace 記錄函數(shù)耗時,或 perf record 記錄 cpu 火焰圖。
2.出現(xiàn)一次后,過好久才會復(fù)現(xiàn)第二次:需要一直開啟 perf trace 或 perf record,直到復(fù)現(xiàn)高延遲。(后續(xù) perf 常駐內(nèi)存后,可同場景 1,使用自動觸發(fā)工具解決)
場景 1,配置高延遲自動觸發(fā)工具去抓包
?
場景 2,使用 root 用戶,在 MAP 容器內(nèi)執(zhí)行如下命令,會一直抓包 6 小時。當(dāng)抓到包后,需要用戶手動殺掉該進程,停止抓包:
./trigger_perf_trace.sh loop
抓 perf trace 和 perf record 包腳本:
可以放到自己的目錄下,例如放到:/home/mogo/data/shizhonghe/trigger_perf_trace.sh
#!/bin/bash -e function ?trigger_once() { ???? now_str=` date ?"+%Y%m%d_%H%M%S.%N" ` ???? date_str=` date ?"+%Y-%m-%d" ` ???? uptime=` cat ?/proc/uptime ?|? awk ?'{print $1}' ` ???? log_dir= /home/mogo/data/log/monitor_cpu_mem_net/ ${date_str} /szh_ ${now_str} ???? pid=` ps ?-ef |? grep ?'__name:=local_planning' ?|? grep ?- v ?grep ?|? awk ?'{print $2}' ` ???? mkdir ?-p ${log_dir} ???? if ?[? "${pid}" ?!=? "" ?] ;? then ???????? perf trace -T -p ${pid} -o? "${log_dir}/perf_trace_${pid}_${now_str}_${uptime}.log" ?sleep ?$1 & ???? else ???????? echo ?"pid null" ?> ${log_dir} /perf_trace_ ${pid}_${now_str}_${uptime}.log ???????? sleep ?$1 ???? fi ???? if ?which ?lsof ?>? /dev/null ;? then ???????? lsof ?-Pn -p ${pid} > ${log_dir} /lsof_ ${pid}_${now_str}.log? ???? fi ???? wait } function ?main() { ???? if ?[? "$1" ?==? "loop" ?] ;? then ???????? local ?run_time=300 ???????? for ?((i=1; i<=72; i++)) ???????? do ???????????? trigger_once ${run_time} ???????? done ???? elif ?[? "$1" ?==? "trigger" ?] ;? then ???????? local ?run_time=5 ???????? trigger_once ${run_time} ???? else ???????? echo ?"param unmatched!" ???? fi } main? "$@" |
使用 perf trace 還是 perf record?
1. perf trace:? linux 內(nèi)核中存在一些埋點,這些埋點會記錄內(nèi)核 api 的時延信息。睡眠時延高(死鎖了、io 操作多等),使用 perf trace 可以排查到
例如: perf trace 顯示工作線程 write 函數(shù)寫文件,耗時 30ms,此時說明寫文件卡住了 30ms,此時一般是同步寫文件了,需要改為異步寫文件
? ? ? ? ? ? perf trace 顯示工作線程中 futex wait 了 30ms,說明等待條件變量等待了 30ms
2.perf record 會對 cpu 采樣,記錄單個進程/多個進程/MAP 容器所有進程的, cpu 運行的函數(shù)樣本,每個采樣點都是一個堆棧,采集一段時間后,會得到很多堆棧,可以把這些堆棧合并到一起,即:火焰圖
某個函數(shù)/進程的 cpu 占用率 = 該函數(shù)/進程的采樣點數(shù)量?÷?總采樣數(shù)量
如果某個模塊
?
使用 perf trace 抓到數(shù)據(jù)后,如何找到高耗時 api
打印耗時 > 20ms 的內(nèi)核 api
import ?sys for ?line? in ??open (sys.argv[ 1 ], "r" ): ???? if ?"local_planning" ?not ?in ?line: ???????? continue ???? l1? = ?line.split( "(" ) ???? if ?len (l1) >? 1 : ???????? l1? = ?l1[ 1 ] ???? else : ???????? continue ???? l2? = ?l1.split( "ms):" ) ???? if ?len (l2) >? 1 ?: ???????? l2? = ?l2[ 0 ] ???? else : ???????? continue ???? tc? = ?float (l2) ???? if ?tc > = ?20.0 ?and ?tc <? 10000 : ??????? print (line) |