您好,登錄后才能下訂單哦!
可用于CPU分析的BPF工具,見下圖標注的這些命令
下表的這些工具有些是屬于BCC或者bpftrace,或為這本書創(chuàng)建的。一些工具同時出現(xiàn)在BCC和bpftrace中。下表出了本節(jié)介紹的工具的來源(BT是bpftrace的縮寫。)
Tool 工具名稱 | Source 來源 | Target 功效/目標 | Description 描述 |
execsnoop | BCC/BT | Sched | Lists new process execution 列出新進程的執(zhí)行 |
exitsnoop | BCC | Sched | Shows process lifespan and exit reason 顯示進程壽命和退出原因 |
runqlat | BCC/BT | Sched | Summarizes CPU run queue latency 總結(jié)CPU運行隊列延遲情況 |
runqlen | BCC/BT | Sched | Summarizes CPU run queue length 總結(jié)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 按類型和過程統(tǒng)計syscall系統(tǒng)調(diào)用 |
argdist | BCC | Syscalls | Can be used for syscall analysis 可以用于系統(tǒng)調(diào)用分析 |
trace | BCC | Syscalls | Can be used for syscall analysis 可以用于系統(tǒng)調(diào)用分析 |
funccount | BCC | Software | Counts function calls 計算函數(shù)調(diào)用 |
softirqs | BCC | Interrupts | Summarizes soft interrupt time 匯總軟中斷時間 |
hardirqs | BCC | Interrupts | Summarizes hard interrupt time 匯總硬中斷時間 |
smpcalls | Book | Kernel | Times SMP remote CPU calls 統(tǒng)計SMP遠程CPU調(diào)用的時間 |
llcstat | BCC | PMCs | Summarizes LLC hit ratio by process 按進程匯總LLC命中率 |
通過exec() syscall 系統(tǒng)調(diào)用來跟蹤新進程。
可以發(fā)現(xiàn)消耗CPU資源的短暫進程的問題,還可以用于調(diào)試軟件的執(zhí)行,包括應(yīng)用程序啟動腳本。
該工具捕獲了用戶使用SSH登錄系統(tǒng)并啟動了包括sshd、groups、mesg在內(nèi)的進程的瞬間。它還顯示了來自系統(tǒng)活動記錄器sar的過程,包括將指標寫入其日志,包括sa1和sadc。
我們可以使用execsnoop查找消耗資源的高速率的短期進程,通常它們可能運行時間很短很難通過top之類的來發(fā)現(xiàn),但是使用execsnoop很容易發(fā)現(xiàn)它。
execsnoop已用于調(diào)試許多生產(chǎn)問題,例如:來自后臺作業(yè)的干擾,應(yīng)用程序啟動緩慢或失敗,容器啟動緩慢或失敗,等等。
execsnoop的工作原理:
跟蹤execve系統(tǒng)調(diào)用(常用的exec(2)變體),并顯示execve(2)參數(shù)和返回值的詳細信息。這將捕獲遵循fork(2)/clone(2)-> exec(2)順序的新進程,以及 re-exec(2)的進程。
有個特殊情況:一些應(yīng)用程序在不調(diào)用exec(2)的情況下創(chuàng)建新進程,例如,在使用fork(2)或單獨克隆(2)創(chuàng)建工作進程池時。因為它們不調(diào)用execve(2),所以execsnoop輸出中不包括這些。這種情況應(yīng)該不常見:應(yīng)用程序應(yīng)該創(chuàng)建工作線程池,而不是進程。 【舉例子: 我們登錄到redis-cli后再執(zhí)行的其它的命令,execsnoop就無法抓取到】
由于進程執(zhí)行速率預(yù)計相對較低(<1000/秒),因此該工具的開銷可以忽略不計。
這里再介紹一個來自Netflix的一個真實問題,我使用execnoop進行了調(diào)試。這發(fā)生在一個用于微基準測試的服務(wù)器上,但是基準測試結(jié)果顯示出太多的差異是不可信任的。當(dāng)系統(tǒng)被認為是空閑的時候,我運行了execnoop,發(fā)現(xiàn)它不是!這些程序每啟動一秒鐘,就會擾亂我們的基準。結(jié)果發(fā)現(xiàn),這是一個配置錯誤的服務(wù),它試圖每秒鐘啟動一次,失敗,然后重新啟動。一旦服務(wù)被停用,這些進程就停止了(正如使用execnoop所確認的那樣),然后基準數(shù)就變得一致了。
? 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工具,可跟蹤進程退出的時間,顯示進程的使用期限和退出原因。期限是從進程創(chuàng)建到終止的時間,并且包括CPU的開啟和關(guān)閉時間。
像execsnoop一樣,exitsnoop可以幫助調(diào)試短期進程的問題,并提供不同的信息來幫助理解此類工作負載。例如:
此輸出顯示退出了許多短期進程,例如cmake,sh和make,這表明一個軟件版本正在運行。1.00秒后,sleep進程成功退出(退出代碼0),而由于KILL信號,另一個sleep進程在7.31秒后退出。這也捕獲了221.25秒后退出的“ DOM Worker”線程。
該工具通過檢測 sched:sched_process_exit 跟蹤點及其參數(shù)來工作,并且還使用bpf_get_current_task(),以便可以從任務(wù)結(jié)構(gòu)中讀取開始時間(不穩(wěn)定的接口詳細信息)。由于此跟蹤點很少觸發(fā),因此該工具的開銷可以忽略不計。
本人的實戰(zhàn)截圖:
runqlat是一個BCC和bpftrace工具,用于測量CPU調(diào)度程序延遲,通常稱為運行隊列延遲(即使不再使用運行隊列實現(xiàn))。這對于識別和量化CPU飽和問題很有用,在CPU飽和問題中,對CPU資源的需求超出了服務(wù)能力。runqlat度量的指標是每個線程(任務(wù))等待其打開CPU所花費的時間。
下圖顯示了在48核CPU生產(chǎn)API實例上運行的BCC runqlat在系統(tǒng)范圍內(nèi)的CPU利用率約為42%(可以用top命令查看到CPU的利用率)。runqlat的參數(shù)為10 1,表示以設(shè)置10秒間隔,僅輸出一次:
此輸出表明,在大多數(shù)情況下,線程等待的時間少于15微秒,直方圖中的模式介于2到15微秒之間。這是相對較快的(健康系統(tǒng)的一個示例),并且對于運行在42%CPU利用率上的系統(tǒng)來說是預(yù)期的。在此示例中,有時運行隊列延遲高達8到16毫秒存儲桶,但這些異常值是異常的。
runqlat的原理:
通過檢測調(diào)度程序喚醒和上下文切換事件來確定從喚醒到運行的時間。注意: 這些事件在繁忙的生產(chǎn)系統(tǒng)上可能非常頻繁,每秒超過一百萬個事件。即使對BPF進行了優(yōu)化,以這些速率,即使每個事件增加一微秒也會導(dǎo)致明顯的開銷。需要小心使用runqlat這個工具。
示例:如果您在一個10核的系統(tǒng)上的上下文切換速率為1M/sec,則每個上下文切換增加1微秒將消耗10%的CPU資源(計算方法: 100%×(1×1000000/10×1000000) )。有關(guān)BPF開銷的一些實際測量值,請參見第18章,每個事件通常小于一微秒。
一個使用runqlat診斷案例
在一個36核CPU的構(gòu)建服務(wù)器進行軟件構(gòu)建操作,其中并行作業(yè)的數(shù)量被錯誤地設(shè)置為72,從而導(dǎo)致CPU超載。觀測到的截圖如下:
現(xiàn)在的分布是三模態(tài),最慢的模式以8到16毫秒的桶為中心.這顯示了線程的大量等待(小于15微秒內(nèi)算健康指標)。
可以直接從其他工具和指標中識別出此特定問題。例如,sar可以顯示CPU利用率(-u)和運行隊列指標(-q)
可以看到,當(dāng)前系統(tǒng) CPU idle空閑為0, 全負荷工作。 另外, runq-sz平均運行隊列大小為72(包括正在運行和可運行),也大幅超過了可用的36個CPU。
runqlen是一個BCC和bpftrace工具,用于對CPU運行隊列的長度進行采樣,計算有多少任務(wù)在等待輪到他們,并將其顯示為線性直方圖。這可以用來進一步描述運行隊列延遲的問題或作為更便宜的近似值。
下圖顯示了在48個CPU生產(chǎn)API實例上運行的BCC的runqlet,該實例在系統(tǒng)范圍內(nèi)的CPU利用率約為42%(與先前在runqlat中顯示的實例相同)。runqlen的參數(shù)為 10 1,以設(shè)置10秒間隔,僅輸出一次:
這表明在大多數(shù)情況下,運行隊列長度為零,這意味著線程無需等待輪到他們。
我將運行隊列長度描述為輔助性能指標,將運行隊列延遲描述為主要性能。與長度不同,延遲會直接和成比例地影響性能。想象一下在雜貨店加入結(jié)帳行。對您來說更重要的是:線路的長度或您實際花費的等待時間?runqlat更重要。那么,為什么要使用runqlen?
首先,可以使用runqlen進一步描述在runqlat中發(fā)現(xiàn)的問題,并解釋延遲如何變高。其次,runqlen采用99赫茲的定時采樣,而runqlat跟蹤調(diào)度程序事件。與runqlat的調(diào)度程序跟蹤相比,此定時采樣的開銷可忽略不計。對于24x7全天候監(jiān)控,最好先使用runqlen來識別問題(因為運行起來更便宜),然后再使用runqlat臨時量化延遲。
四線程,一個CPU的一個示例:
在此示例中,將四個繁忙線程的CPU工作負載綁定到CPU0。執(zhí)行runqlen -C以顯示每個CPU的直方圖:
CPU 0上的運行隊列長度為三個:一個線程在CPU上等待三個線程。此每個CPU的輸出對于檢查調(diào)度程序平衡非常有用。
小實驗:
我們執(zhí)行5次這個單行命令taskset -c 0 sh -c 'while :; do :; done' & ,這個循環(huán)操作綁定在cpu0上運行,然后執(zhí)行 runqlen可以看到如下結(jié)果,明顯可以看到cpu0上有很多運行隊列的堆積,而cpu1上堆積基本都是0。
runqslower是一個BCC工具,它列出了運行隊列等待時間超過可配置閾值的實例,并顯示了遭受等待時間及其持續(xù)時間的過程。
以下示例來自當(dāng)前在系統(tǒng)范圍內(nèi)以45%CPU利用率運行的48 CPU生產(chǎn)API實例:
此輸出表明,在13秒的時間內(nèi), 有10個運行隊列等待時間超過默認閾值10000微秒(10毫秒)的情況。對于具有55%空閑CPU余量的服務(wù)器來說,這似乎令人驚訝,但這是一個繁忙的多線程應(yīng)用程序,在調(diào)度程序可以將線程遷移到空閑CPU之前,運行隊列可能不平衡。該工具可以確認受影響的應(yīng)用程序。
該工具當(dāng)前通過將kprobes用于內(nèi)核函數(shù)ttwu_do_wakeup(),wake_up_new_task()和finish_task_switch() 來工作。將來的版本應(yīng)使用類似于runqlat的bpftrace版本的代碼切換到調(diào)度程序跟蹤點。開銷與runqlat相似;由于kprobes的成本,即使在runqslower不輸出任何輸出的情況下,它也會在繁忙的系統(tǒng)上引起明顯的開銷。
cpudist是一個BCC工具,用于顯示每個線程喚醒的CPU時間分布。這可用于幫助表征CPU工作負載,為以后的調(diào)整和設(shè)計決策提供詳細信息。
例如,從一個48 核CPU生產(chǎn)實例中:
此輸出表明生產(chǎn)應(yīng)用程序通常僅在CPU上花費很短的時間:從0到127微秒。
下面的圖,這是一個CPU繁重的工作負載,具有比可用CPU更多的繁忙線程,并且具有以毫秒(-m)為單位的直方圖:
現(xiàn)在有一種CPU持續(xù)時間從4到15毫秒的模式:這很可能是線程耗盡了調(diào)度程序的時間量,然后遇到了非自愿的上下文切換。
該工具用于幫助了解Netflix的生產(chǎn)變化,其中機器學(xué)習(xí)應(yīng)用程序開始運行的速度快了三倍。perf命令用于顯示上下文切換速率已降低,而cpudist用于解釋其影響:應(yīng)用程序現(xiàn)在通常在上下文切換之間運行兩到四毫秒,而更早的時候只能在0到3微秒之間運行,然后再被上下文切換中斷。
注意:
cpudist通過跟蹤調(diào)度程序上下文切換事件來工作,該事件在繁忙的生產(chǎn)工作負載上非常頻繁(超過一百萬個事件/秒)。與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工具集內(nèi)。 個人認為只要大致了解下這個命令即可。
cpufreq對CPU頻率進行采樣,并將其顯示為系統(tǒng)范圍的直方圖,并帶有每個進程的名稱直方圖。這僅適用于更改頻率的CPU縮放調(diào)節(jié)器,例如節(jié)電,并可用于確定應(yīng)用程序運行的時鐘速度。
profile是一個BCC工具,它以一定的時間間隔對堆棧跟蹤進行采樣,并報告堆棧跟蹤的頻率計數(shù)。這是BCC中了解CPU消耗的最有用的工具,因為它總結(jié)了消耗CPU資源的幾乎所有代碼路徑。由于事件率固定為可以調(diào)整的采樣率,因此它也可以以相對可忽略的開銷使用。
根據(jù)profile的結(jié)果,我們可以繪制火焰圖
$ profile -af 30 > out.stacks01
$ git clone https://github.com/brendangregg/FlameGraph
$ cd FlameGraph
$ ./flamegraph.pl --color=java < ../out.stacks01 > out.svg
然后即可輸出一幅火焰圖。
使profile與其他CPU探查器不同的原因在于,為了提高效率,此頻率計數(shù)是在內(nèi)核空間中計算的。其他基于內(nèi)核的探查器,例如perf,會將每個采樣的堆棧跟蹤發(fā)送到用戶空間,在該用戶跟蹤中將其后處理為摘要。這可能會占用大量CPU資源,并且取決于調(diào)用,它還可能涉及文件系統(tǒng)和磁盤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工具,用于總結(jié)阻塞線程和關(guān)閉CPU所花費的時間,并顯示堆棧跟蹤信息以說明原因。
對于CPU分析,此工具說明了為什么線程未在CPU上運行。
與profile對應(yīng);在它們之間,它們顯示了線程在系統(tǒng)上花費的全部時間:使用profile的CPU時間和使用offcputime的CPU時間。
offcputime已用于查找各種生產(chǎn)問題,包括查找在鎖獲取中阻塞的意外時間以及負責(zé)的堆棧跟蹤。
注意:
offcputime通過檢測上下文切換并記錄從線程離開CPU到返回CPU的時間以及堆棧跟蹤來工作。為了提高效率,在內(nèi)核上下文中對時間和堆棧跟蹤進行了頻率計數(shù)。但是,上下文切換事件可能會非常頻繁,并且對于繁忙的生產(chǎn)工作負載,此工具的開銷可能會變得非常大(例如,> 10%)。該工具最好只在短時間內(nèi)運行,以最大程度地減少生產(chǎn)影響。
offCPU time火焰圖
與profile一樣,offcputime的輸出可能非常冗長,以至于您可以發(fā)現(xiàn)最好將它作為火焰圖進行檢查。可以將offcputime可視化為非CPU時間火焰圖。
相關(guān)繪圖的命令如下:
# 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工具,可以對函數(shù)和其他事件進行頻率計數(shù)。
它可用于為軟件CPU使用情況提供更多上下文,顯示調(diào)用哪些函數(shù)以及調(diào)用頻率。profile可能能夠顯示某個功能在CPU上很熱,但無法解釋為什么:該功能是否運行緩慢,或者每秒是否被簡單調(diào)用了數(shù)百萬次。
TIPS:profile不能輕易解釋這一點。包括profile在內(nèi)的探查器對CPU指令指針進行采樣,因此與該函數(shù)的反匯編進行比較可能會顯示該函數(shù)是卡在循環(huán)中還是被調(diào)用多次。
例如,通過匹配以 tcp_ 開頭的功能,可以對繁忙的生產(chǎn)實例上的內(nèi)核TCP功能進行頻率計數(shù):
可以使用-i 1 使其每1秒輸出一次。例如,較早的profile輸出顯示函數(shù)get_page_from_freelist()在CPU上很熱。是因為它經(jīng)常被調(diào)用還是因為它運行緩慢?可以用如下命令來測量其每秒速率:
這通過使用函數(shù)的動態(tài)跟蹤來進行:內(nèi)核函數(shù)使用kprobes,用戶級函數(shù)使用uprob。此工具的開銷與功能的速率有關(guān)。某些函數(shù)(例如malloc() 和get_page_from_freelist() )往往會頻繁發(fā)生,因此對其進行跟蹤可能會大大降低目標應(yīng)用程序的速度,超過10%,請謹慎使用。
softirqs是一個BCC工具,它顯示了花費在soft IRQ(軟中斷)所花費的時間。
可以通過不同的工具輕松獲得系統(tǒng)范圍的軟中斷時間。例如,mpstat將其顯示為%soft。也有 /proc/softirqs 顯示軟IRQ事件的計數(shù)。
BCC softirqs工具的不同之處在于,它可以顯示每個軟IRQ的時間,而不是事件計數(shù)。
例如,從一個48 CPU生產(chǎn)實例和一個10秒的跟蹤中:
此輸出顯示,花費在net_rx花費的時間最多,總計1358毫秒。這很重要,因為在該48 CPU系統(tǒng)上,它占CPU時間的3%。
softirqs通過使用irq:softirq_enter和irq:softirq_exit跟蹤點來工作。該工具的開銷與事件發(fā)生率有關(guān),這對于繁忙的生產(chǎn)系統(tǒng)和較高的網(wǎng)絡(luò)數(shù)據(jù)包發(fā)生率可能會很高。謹慎使用并檢查開銷。
hardirqs是一個BCC工具,它顯示了花費在hard IRQ(硬中斷)所花費的時間。
硬中斷中的系統(tǒng)級時間可以從其他工具輕松獲得。例如,mpstat將其顯示為%irq。也有 /proc/interrupts 顯示hard IRQ事件的計數(shù)。
BCC hardirqs工具的不同之處在于,它可以顯示每個硬IRQ的時間,而不是事件計數(shù)。
下面是mpstat -P ALL 1 的部分截圖(這臺ecs的負載很低)
hardirqs可以提供CPU分析器不可見的CPU使用情況信息。有關(guān)缺少硬件PMU的云實例的性能分析,請參見第6.2.4節(jié)的內(nèi)部部分。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。