Go 高效能系列教程:讀懂 pprof 生成的報告
pprof 的目標是生成視覺化的檢測報告。報告是根據採集的樣本資料從一個跟節點位置開始按呼叫關係生成層次化的結構。每個位置包含兩個值:
- flat:當前位置自身消耗的值(不包含函式內的呼叫消耗)
- cum:當前位置及子位置累計的消耗值(即當前函式以及所有呼叫的函式總消耗)
pprof 生成報告的形式有兩種:文字形式和視覺化圖形
文字形式報告
pprof 的文字報告用文字的格式展示了位置的層次結構
- -text:列印每個位置條目,每行一個,包括單位值和累計值
- -tree:按樹狀列印每個位置條目,包括該職位的父節點和子節點
- -peek=regex:列印位置條目及其所有前置項和後續項,而不修剪任何條目
- -traces:列印每一行的樣本
文字報告中有 5 個指標:Flat、Flat%、Sum%、Cum、Cum%
-
Flat
:函式自身執行耗時 -
Flat%
:函式自身耗時比例 -
Sum%
:指的就是每一行的flat%
與上面所有行的flat%
總和 -
Cum
:當前函式加上它所有呼叫棧的執行總耗時 -
Cum%
:當前函式加上它所有呼叫棧的執行總耗時比例
舉例說明:函式demo
由三部分組成:呼叫函式foo
、自己直接處理一些事情、呼叫函式bar
,其中呼叫函式foo
耗時 1 秒,自己直接處理事情耗時 3 秒,呼叫函式bar
耗時 2 秒,那麼函式demo
的flat
耗時就是 3 秒,cum
耗時就是 6 秒。
func demo() {
foo() // takes 1s
do something directly // takes 3s
bar() // takes 2s
}
如下圖示例:
Sum% 值是當前行及上面行的累加和佔比。如圖所示中,第一行的 Flat% 是 98.41%,則第一行的 Sum% 是 98.41%。第二行的 Flat% 是 1.59%,則第二行的 Sum% 則是 1.59%+98.41%=100%。
視覺化圖形
在圖形化的包中包含節點、節點之間的邊、字型三個元素。而每個元素又具有顏色和大小兩個屬性。下面我們一一解析各個元素和屬性所代表的含義。
節點顏色:
- 紅色代表 cum 值為正,且越大
- 綠色代表 cum 值為負,且越小。
- 灰色代表 cum 值接近 0
節點字型大小:
- 字型越大代表較大的絕對單位值
- 字型越小代表較小的絕對單位值
邊線及權重
- 較粗的邊線代表該路徑下使用了更多的資源
- 較細的邊線代表該路徑下使用了較少的資源
邊線顏色
- 紅色代表值為正,且越大
- 綠色代表值為負,且越小
- 灰色代表值接近 0
邊線樣式
- 虛線邊:兩個連線位置之間的某些節點已被刪除,未顯示全。為限制圖形整體的大小,pprof 會自動裁剪一部分節點,而非都顯示。
- 實線邊:一個位置直接呼叫另一個位置
- 內聯邊標記:被呼叫函式已經被內聯到呼叫函式中
我們以下面的圖形為例::
-
節點
- (*Rand).Read 節點的字型是小字型,顏色為灰色,代表自身值和累計值都比較小,接近於 0
- (*compressor).deflate 節點的字型較大,節點為紅色,代表自身值和累計值都較大。
- (*Writer).Flush 節點的字型較小,節點為紅色,代表是自身值較小,但累計值較大。
-
邊
- 在(*Writer).Write 和 (*compressor).write 之間的邊:
- 因為是虛線,在這兩個節點之間有些節點被刪除了
- 因為是紅色粗線,說明在這兩個節點之間的呼叫棧上耗費了更多的資源
- 在 (*Rand).Read 和 read 之間的邊:
- 因為是虛線,所以在這兩個節點之間有些節點被刪除了
- 因為是灰色細線,說明在這兩個節點之間的呼叫棧上耗費了較少的資源,接近於 0
- 在 read 和 (*rngSource).Int63 之間的邊:
- 因為是實線,在這兩個節點之間沒有其他節點,是直接呼叫。
- 因為是灰色細線,說明在這兩個節點之間的呼叫棧上耗費了較少的資源,接近於 0
- 在(*Writer).Write 和 (*compressor).write 之間的邊:
總結
在圖形化中,顏色越深(紅色)、字型越大代表消耗的資源越多(如果是 cpu 效能則耗時更長、如果是記憶體則佔用更高)。在邊線路徑中,邊線顏色越深、越粗,代表該路徑下消耗的資源越多,反之代表消耗的資源越少。
在圖形化中,pprof 為了圖形化的整體大小,會自動刪減一些節點,所以,圖形介面中顯示的並不是所有的節點。這裡通過邊線是實線還是虛線來體現。虛線代表兩個節點之間有其他的節點呼叫,但未顯示。實線則代表兩個節點之間是直接呼叫的。
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- go pprof命令Go
- go tool pprofGo
- 讀懂Netty的高效能架構之道Netty架構
- Go 高效能系列教程之一:基準測試Go
- Go 高效能系列教程之三:編譯器優化Go編譯優化
- Go 高效能系列教程之二:效能評估和分析Go
- Go 高效能系列教程之五:記憶體和垃圾回收Go記憶體
- 報表生成器Stimulsoft分層報告教程
- Go 高效能系列教程之六:一些建議和實踐Go
- 一圖讀懂中國路跑運動報告
- 一文讀懂 .NET 中的高效能佇列 Channel佇列
- SEQSVR:Go + MySQL 實現的高效能 ID 生成服務VRGoMySql
- Go pprof 認知到實踐Go
- 一文讀懂Go Http Server原理GoHTTPServer
- Go 系列教程 —— 25. MutexGoMutex
- 一文讀懂系列-JVM垃圾收集JVM
- Go藉助PProf的一次效能優化Go優化
- Dig101:Go之讀懂map的底層設計Go
- Dig101:Go 之讀懂 map 的底層設計Go
- 一篇文章教你如何讀懂 JMeter聚合報告引數!JMeter
- 小學生也能讀懂的Docker入門教程Docker
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- Fuzzing: 一文讀懂Go Fuzzing使用和原理Go
- 一文讀懂 Go sync.Cond 設計Go
- 秒懂系列,超詳細Java列舉教程!!!Java
- 基於 go pprof` 與 go trace 進行持續效能剖析Go
- rpc的正確開啟方式|讀懂Go原生net/rpc包RPCGo
- golang 使用pprof和go-torch做效能分析Golang
- 一圖讀懂k8s informer client-goK8SORMclientGo
- 一文徹底讀懂 hystrix-go 原始碼Go原始碼
- Go基礎系列:惰性數值生成器Go
- 告別DNS劫持,一文讀懂DoHDNS
- 報表工具如何生成 word 報告?
- golang pprof監控系列(2) —— memory,block,mutex 使用GolangBloCMutex
- 一文讀懂Go 1.20引入的PGO效能最佳化Go
- ORACLE AWR效能報告和ASH效能報告的解讀Oracle
- 2021 Go 趨勢報告Go
- golang pprof 監控系列(4) —— goroutine thread 統計原理Golangthread