您好,登錄后才能下訂單哦!
可用于CPU分析的BPF工具,見下圖標注的這些命令
下表的這些工具有些是屬于BCC或者bpftrace,或為這本書創建的。一些工具同時出現在BCC和bpftrace中。下表出了本節介紹的工具的來源(BT是bpftrace的縮寫。)
Tool 工具名稱 | Source 來源 | Target 功效/目標 | Description 描述 |
execsnoop | BCC/BT | Sched | Lists new process execution 列出新進程的執行 |
exitsnoop | BCC | Sched | Shows process lifespan and exit reason 顯示進程壽命和退出原因 |
runqlat | BCC/BT | Sched | Summarizes CPU run queue latency 總結CPU運行隊列延遲情況 |
runqlen | BCC/BT | Sched | Summarizes CPU run queue length 總結CPU運行隊列長度 |
runqslower | BCC | Sched | Prints run queue waits slower than a threshold 打印等待時間慢于閾值的運行隊列(單位us) |
cpudist | BCC | Sched | Summarizes on-CPU time 匯總on-CPU的時間 |
cpufreq | Book | CPUs | Samples CPU frequency by process 按進程采樣CPU頻率 |
profile | BCC | CPUs | Samples CPU stack traces 采樣CPU堆棧跟蹤 |
offcputime | BCC/book | Sched | Summarizes off-CPU stack traces and times 匯總off-CPU堆棧跟蹤和時間 |
syscount | BCC/BT | Syscalls | Counts system calls by type and process 按類型和過程統計syscall系統調用 |
argdist | BCC | Syscalls | Can be used for syscall analysis 可以用于系統調用分析 |
trace | BCC | Syscalls | Can be used for syscall analysis 可以用于系統調用分析 |
funccount | BCC | Software | Counts function calls 計算函數調用 |
softirqs | BCC | Interrupts | Summarizes soft interrupt time 匯總軟中斷時間 |
hardirqs | BCC | Interrupts | Summarizes hard interrupt time 匯總硬中斷時間 |
smpcalls | Book | Kernel | Times SMP remote CPU calls 統計SMP遠程CPU調用的時間 |
llcstat | BCC | PMCs | Summarizes LLC hit ratio by process 按進程匯總LLC命中率 |
通過exec() syscall 系統調用來跟蹤新進程。
可以發現消耗CPU資源的短暫進程的問題,還可以用于調試軟件的執行,包括應用程序啟動腳本。
該工具捕獲了用戶使用SSH登錄系統并啟動了包括sshd、groups、mesg在內的進程的瞬間。它還顯示了來自系統活動記錄器sar的過程,包括將指標寫入其日志,包括sa1和sadc。
我們可以使用execsnoop查找消耗資源的高速率的短期進程,通常它們可能運行時間很短很難通過top之類的來發現,但是使用execsnoop很容易發現它。
execsnoop已用于調試許多生產問題,例如:來自后臺作業的干擾,應用程序啟動緩慢或失敗,容器啟動緩慢或失敗,等等。
execsnoop的工作原理:
跟蹤execve系統調用(常用的exec(2)變體),并顯示execve(2)參數和返回值的詳細信息。這將捕獲遵循fork(2)/clone(2)-> exec(2)順序的新進程,以及 re-exec(2)的進程。
有個特殊情況:一些應用程序在不調用exec(2)的情況下創建新進程,例如,在使用fork(2)或單獨克隆(2)創建工作進程池時。因為它們不調用execve(2),所以execsnoop輸出中不包括這些。這種情況應該不常見:應用程序應該創建工作線程池,而不是進程。 【舉例子: 我們登錄到redis-cli后再執行的其它的命令,execsnoop就無法抓取到】
由于進程執行速率預計相對較低(<1000/秒),因此該工具的開銷可以忽略不計。
這里再介紹一個來自Netflix的一個真實問題,我使用execnoop進行了調試。這發生在一個用于微基準測試的服務器上,但是基準測試結果顯示出太多的差異是不可信任的。當系統被認為是空閑的時候,我運行了execnoop,發現它不是!這些程序每啟動一秒鐘,就會擾亂我們的基準。結果發現,這是一個配置錯誤的服務,它試圖每秒鐘啟動一次,失敗,然后重新啟動。一旦服務被停用,這些進程就停止了(正如使用execnoop所確認的那樣),然后基準數就變得一致了。
? execsnoop --help
usage: execsnoop [-h] [-T] [-t] [-x] [-q] [-n NAME] [-l LINE]
[--max-args MAX_ARGS]
Trace exec() syscalls
optional arguments:
-h, --help show this help message and exit
-T, --time include time column on output (HH:MM:SS)
-t, --timestamp include timestamp on output
-x, --fails include failed exec()s
-q, --quote Add quotemarks (") around arguments.
-n NAME, --name NAME only print commands matching this name (regex), any arg
-l LINE, --line LINE only print commands where arg contains this line (regex)
--max-args MAX_ARGS maximum number of arguments parsed and displayed,defaults to 20
examples:
./execsnoop # trace all exec() syscalls
./execsnoop -x # include failed exec()s
./execsnoop -T # include time (HH:MM:SS)
./execsnoop -t # include timestamps
./execsnoop -q # add "quotemarks" around arguments
./execsnoop -n main # only print command lines containing "main"
./execsnoop -l tpkg # only print command where arguments contains "tpkg"
exitsnoop是一個BCC工具,可跟蹤進程退出的時間,顯示進程的使用期限和退出原因。期限是從進程創建到終止的時間,并且包括CPU的開啟和關閉時間。
像execsnoop一樣,exitsnoop可以幫助調試短期進程的問題,并提供不同的信息來幫助理解此類工作負載。例如:
此輸出顯示退出了許多短期進程,例如cmake,sh和make,這表明一個軟件版本正在運行。1.00秒后,sleep進程成功退出(退出代碼0),而由于KILL信號,另一個sleep進程在7.31秒后退出。這也捕獲了221.25秒后退出的“ DOM Worker”線程。
該工具通過檢測 sched:sched_process_exit 跟蹤點及其參數來工作,并且還使用bpf_get_current_task(),以便可以從任務結構中讀取開始時間(不穩定的接口詳細信息)。由于此跟蹤點很少觸發,因此該工具的開銷可以忽略不計。
本人的實戰截圖:
runqlat是一個BCC和bpftrace工具,用于測量CPU調度程序延遲,通常稱為運行隊列延遲(即使不再使用運行隊列實現)。這對于識別和量化CPU飽和問題很有用,在CPU飽和問題中,對CPU資源的需求超出了服務能力。runqlat度量的指標是每個線程(任務)等待其打開CPU所花費的時間。
下圖顯示了在48核CPU生產API實例上運行的BCC runqlat在系統范圍內的CPU利用率約為42%(可以用top命令查看到CPU的利用率)。runqlat的參數為10 1,表示以設置10秒間隔,僅輸出一次:
此輸出表明,在大多數情況下,線程等待的時間少于15微秒,直方圖中的模式介于2到15微秒之間。這是相對較快的(健康系統的一個示例),并且對于運行在42%CPU利用率上的系統來說是預期的。在此示例中,有時運行隊列延遲高達8到16毫秒存儲桶,但這些異常值是異常的。
runqlat的原理:
通過檢測調度程序喚醒和上下文切換事件來確定從喚醒到運行的時間。注意: 這些事件在繁忙的生產系統上可能非常頻繁,每秒超過一百萬個事件。即使對BPF進行了優化,以這些速率,即使每個事件增加一微秒也會導致明顯的開銷。需要小心使用runqlat這個工具。
示例:如果您在一個10核的系統上的上下文切換速率為1M/sec,則每個上下文切換增加1微秒將消耗10%的CPU資源(計算方法: 100%×(1×1000000/10×1000000) )。有關BPF開銷的一些實際測量值,請參見第18章,每個事件通常小于一微秒。
一個使用runqlat診斷案例
在一個36核CPU的構建服務器進行軟件構建操作,其中并行作業的數量被錯誤地設置為72,從而導致CPU超載。觀測到的截圖如下:
現在的分布是三模態,最慢的模式以8到16毫秒的桶為中心.這顯示了線程的大量等待(小于15微秒內算健康指標)。
可以直接從其他工具和指標中識別出此特定問題。例如,sar可以顯示CPU利用率(-u)和運行隊列指標(-q)
可以看到,當前系統 CPU idle空閑為0, 全負荷工作。 另外, runq-sz平均運行隊列大小為72(包括正在運行和可運行),也大幅超過了可用的36個CPU。
runqlen是一個BCC和bpftrace工具,用于對CPU運行隊列的長度進行采樣,計算有多少任務在等待輪到他們,并將其顯示為線性直方圖。這可以用來進一步描述運行隊列延遲的問題或作為更便宜的近似值。
下圖顯示了在48個CPU生產API實例上運行的BCC的runqlet,該實例在系統范圍內的CPU利用率約為42%(與先前在runqlat中顯示的實例相同)。runqlen的參數為 10 1,以設置10秒間隔,僅輸出一次:
這表明在大多數情況下,運行隊列長度為零,這意味著線程無需等待輪到他們。
我將運行隊列長度描述為輔助性能指標,將運行隊列延遲描述為主要性能。與長度不同,延遲會直接和成比例地影響性能。想象一下在雜貨店加入結帳行。對您來說更重要的是:線路的長度或您實際花費的等待時間?runqlat更重要。那么,為什么要使用runqlen?
首先,可以使用runqlen進一步描述在runqlat中發現的問題,并解釋延遲如何變高。其次,runqlen采用99赫茲的定時采樣,而runqlat跟蹤調度程序事件。與runqlat的調度程序跟蹤相比,此定時采樣的開銷可忽略不計。對于24x7全天候監控,最好先使用runqlen來識別問題(因為運行起來更便宜),然后再使用runqlat臨時量化延遲。
四線程,一個CPU的一個示例:
在此示例中,將四個繁忙線程的CPU工作負載綁定到CPU0。執行runqlen -C以顯示每個CPU的直方圖:
CPU 0上的運行隊列長度為三個:一個線程在CPU上等待三個線程。此每個CPU的輸出對于檢查調度程序平衡非常有用。
小實驗:
我們執行5次這個單行命令taskset -c 0 sh -c 'while :; do :; done' & ,這個循環操作綁定在cpu0上運行,然后執行 runqlen可以看到如下結果,明顯可以看到cpu0上有很多運行隊列的堆積,而cpu1上堆積基本都是0。
runqslower是一個BCC工具,它列出了運行隊列等待時間超過可配置閾值的實例,并顯示了遭受等待時間及其持續時間的過程。
以下示例來自當前在系統范圍內以45%CPU利用率運行的48 CPU生產API實例:
此輸出表明,在13秒的時間內, 有10個運行隊列等待時間超過默認閾值10000微秒(10毫秒)的情況。對于具有55%空閑CPU余量的服務器來說,這似乎令人驚訝,但這是一個繁忙的多線程應用程序,在調度程序可以將線程遷移到空閑CPU之前,運行隊列可能不平衡。該工具可以確認受影響的應用程序。
該工具當前通過將kprobes用于內核函數ttwu_do_wakeup(),wake_up_new_task()和finish_task_switch() 來工作。將來的版本應使用類似于runqlat的bpftrace版本的代碼切換到調度程序跟蹤點。開銷與runqlat相似;由于kprobes的成本,即使在runqslower不輸出任何輸出的情況下,它也會在繁忙的系統上引起明顯的開銷。
cpudist是一個BCC工具,用于顯示每個線程喚醒的CPU時間分布。這可用于幫助表征CPU工作負載,為以后的調整和設計決策提供詳細信息。
例如,從一個48 核CPU生產實例中:
此輸出表明生產應用程序通常僅在CPU上花費很短的時間:從0到127微秒。
下面的圖,這是一個CPU繁重的工作負載,具有比可用CPU更多的繁忙線程,并且具有以毫秒(-m)為單位的直方圖:
現在有一種CPU持續時間從4到15毫秒的模式:這很可能是線程耗盡了調度程序的時間量,然后遇到了非自愿的上下文切換。
該工具用于幫助了解Netflix的生產變化,其中機器學習應用程序開始運行的速度快了三倍。perf命令用于顯示上下文切換速率已降低,而cpudist用于解釋其影響:應用程序現在通常在上下文切換之間運行兩到四毫秒,而更早的時候只能在0到3微秒之間運行,然后再被上下文切換中斷。
注意:
cpudist通過跟蹤調度程序上下文切換事件來工作,該事件在繁忙的生產工作負載上非常頻繁(超過一百萬個事件/秒)。與runqlat一樣,此工具的開銷可能很大,因此請謹慎使用。
root@dba-test:~|? cpudist --help
usage: cpudist [-h] [-O] [-T] [-m] [-P] [-L] [-p PID] [interval] [count]
Summarize on-CPU time per task as a histogram.
positional arguments:
interval output interval, in seconds
count number of outputs
optional arguments:
-h, --help show this help message and exit
-O, --offcpu measure off-CPU time # 只顯示CPU以外的時間,而不是CPU上的時間
-T, --timestamp include timestamp on output
-m, --milliseconds millisecond histogram
-P, --pids print a histogram per process ID # 每個進程打印一個直方圖
-L, --tids print a histogram per thread ID
-p PID, --pid PID trace this PID only
examples:
cpudist # summarize on-CPU time as a histogram
cpudist -O # summarize off-CPU time as a histogram
cpudist 1 10 # print 1 second summaries, 10 times
cpudist -mT 1 # 1s summaries, milliseconds, and timestamps
cpudist -P # show each PID separately
cpudist -p 185 # trace PID 185 only
這是個bpftrace腳本文件,不在BCC工具集內。 個人認為只要大致了解下這個命令即可。
cpufreq對CPU頻率進行采樣,并將其顯示為系統范圍的直方圖,并帶有每個進程的名稱直方圖。這僅適用于更改頻率的CPU縮放調節器,例如節電,并可用于確定應用程序運行的時鐘速度。
profile是一個BCC工具,它以一定的時間間隔對堆棧跟蹤進行采樣,并報告堆棧跟蹤的頻率計數。這是BCC中了解CPU消耗的最有用的工具,因為它總結了消耗CPU資源的幾乎所有代碼路徑。由于事件率固定為可以調整的采樣率,因此它也可以以相對可忽略的開銷使用。
根據profile的結果,我們可以繪制火焰圖
$ profile -af 30 > out.stacks01
$ git clone https://github.com/brendangregg/FlameGraph
$ cd FlameGraph
$ ./flamegraph.pl --color=java < ../out.stacks01 > out.svg
然后即可輸出一幅火焰圖。
使profile與其他CPU探查器不同的原因在于,為了提高效率,此頻率計數是在內核空間中計算的。其他基于內核的探查器,例如perf,會將每個采樣的堆棧跟蹤發送到用戶空間,在該用戶跟蹤中將其后處理為摘要。這可能會占用大量CPU資源,并且取決于調用,它還可能涉及文件系統和磁盤I/O來記錄樣本。profile避免了這些費用。
root@dba-test:~|? profile --help
usage: profile [-h] [-p PID | -L TID] [-U | -K] [-F FREQUENCY | -c COUNT] [-d]
[-a] [-I] [-f] [--stack-storage-size STACK_STORAGE_SIZE]
[-C CPU]
[duration]
Profile CPU stack traces at a timed interval
positional arguments:
duration duration of trace, in seconds
optional arguments:
-h, --help show this help message and exit
-p PID, --pid PID profile process with this PID only
-L TID, --tid TID profile thread with this TID only
-U, --user-stacks-only show stacks from user space only (no kernel space stacks)
-K, --kernel-stacks-only show stacks from kernel space only (no user space stacks)
-F FREQUENCY, --frequency FREQUENCY sample frequency, Hertz
-c COUNT, --count COUNT sample period, number of events
-d, --delimited insert delimiter between kernel/user stacks
-a, --annotations add _[k] annotations to kernel frames
-I, --include-idle include CPU idle stacks
-f, --folded output folded format, one line per stack (for flame graphs)
--stack-storage-size STACK_STORAGE_SIZE
the number of unique stack traces that can be stored and displayed (default 16384)
-C CPU, --cpu CPU cpu number to run profile on
examples:
./profile # profile stack traces at 49 Hertz until Ctrl-C
./profile -F 99 # profile stack traces at 99 Hertz
./profile -c 1000000 # profile stack traces every 1 in a million events
./profile 5 # profile at 49 Hertz for 5 seconds only
./profile -f 5 # output in folded format for flame graphs
./profile -p 185 # only profile process with PID 185
./profile -L 185 # only profile thread with TID 185
./profile -U # only show user space stacks (no kernel)
./profile -K # only show kernel space stacks (no user)
offcputime是一個BCC和bpftrace工具,用于總結阻塞線程和關閉CPU所花費的時間,并顯示堆棧跟蹤信息以說明原因。
對于CPU分析,此工具說明了為什么線程未在CPU上運行。
與profile對應;在它們之間,它們顯示了線程在系統上花費的全部時間:使用profile的CPU時間和使用offcputime的CPU時間。
offcputime已用于查找各種生產問題,包括查找在鎖獲取中阻塞的意外時間以及負責的堆棧跟蹤。
注意:
offcputime通過檢測上下文切換并記錄從線程離開CPU到返回CPU的時間以及堆棧跟蹤來工作。為了提高效率,在內核上下文中對時間和堆棧跟蹤進行了頻率計數。但是,上下文切換事件可能會非常頻繁,并且對于繁忙的生產工作負載,此工具的開銷可能會變得非常大(例如,> 10%)。該工具最好只在短時間內運行,以最大程度地減少生產影響。
offCPU time火焰圖
與profile一樣,offcputime的輸出可能非常冗長,以至于您可以發現最好將它作為火焰圖進行檢查。可以將offcputime可視化為非CPU時間火焰圖。
相關繪圖的命令如下:
# offcputime -fKu 5 > out.offcputime01.txt
$ flamegraph.pl --hash --bgcolors=blue --title="Off-CPU Time Flame Graph" < out.offcputime01.txt > out.offcputime01.svg
funccount是一種BCC工具,可以對函數和其他事件進行頻率計數。
它可用于為軟件CPU使用情況提供更多上下文,顯示調用哪些函數以及調用頻率。profile可能能夠顯示某個功能在CPU上很熱,但無法解釋為什么:該功能是否運行緩慢,或者每秒是否被簡單調用了數百萬次。
TIPS:profile不能輕易解釋這一點。包括profile在內的探查器對CPU指令指針進行采樣,因此與該函數的反匯編進行比較可能會顯示該函數是卡在循環中還是被調用多次。
例如,通過匹配以 tcp_ 開頭的功能,可以對繁忙的生產實例上的內核TCP功能進行頻率計數:
可以使用-i 1 使其每1秒輸出一次。例如,較早的profile輸出顯示函數get_page_from_freelist()在CPU上很熱。是因為它經常被調用還是因為它運行緩慢?可以用如下命令來測量其每秒速率:
這通過使用函數的動態跟蹤來進行:內核函數使用kprobes,用戶級函數使用uprob。此工具的開銷與功能的速率有關。某些函數(例如malloc() 和get_page_from_freelist() )往往會頻繁發生,因此對其進行跟蹤可能會大大降低目標應用程序的速度,超過10%,請謹慎使用。
softirqs是一個BCC工具,它顯示了花費在soft IRQ(軟中斷)所花費的時間。
可以通過不同的工具輕松獲得系統范圍的軟中斷時間。例如,mpstat將其顯示為%soft。也有 /proc/softirqs 顯示軟IRQ事件的計數。
BCC softirqs工具的不同之處在于,它可以顯示每個軟IRQ的時間,而不是事件計數。
例如,從一個48 CPU生產實例和一個10秒的跟蹤中:
此輸出顯示,花費在net_rx花費的時間最多,總計1358毫秒。這很重要,因為在該48 CPU系統上,它占CPU時間的3%。
softirqs通過使用irq:softirq_enter和irq:softirq_exit跟蹤點來工作。該工具的開銷與事件發生率有關,這對于繁忙的生產系統和較高的網絡數據包發生率可能會很高。謹慎使用并檢查開銷。
hardirqs是一個BCC工具,它顯示了花費在hard IRQ(硬中斷)所花費的時間。
硬中斷中的系統級時間可以從其他工具輕松獲得。例如,mpstat將其顯示為%irq。也有 /proc/interrupts 顯示hard IRQ事件的計數。
BCC hardirqs工具的不同之處在于,它可以顯示每個硬IRQ的時間,而不是事件計數。
下面是mpstat -P ALL 1 的部分截圖(這臺ecs的負載很低)
hardirqs可以提供CPU分析器不可見的CPU使用情況信息。有關缺少硬件PMU的云實例的性能分析,請參見第6.2.4節的內部部分。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。