Go 高效能系列教程:讀懂 pprof 生成的報告

yudotyang發表於2021-05-29

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 秒,那麼函式demoflat耗時就是 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

總結

在圖形化中,顏色越深(紅色)、字型越大代表消耗的資源越多(如果是 cpu 效能則耗時更長、如果是記憶體則佔用更高)。在邊線路徑中,邊線顏色越深、越粗,代表該路徑下消耗的資源越多,反之代表消耗的資源越少。

在圖形化中,pprof 為了圖形化的整體大小,會自動刪減一些節點,所以,圖形介面中顯示的並不是所有的節點。這裡通過邊線是實線還是虛線來體現。虛線代表兩個節點之間有其他的節點呼叫,但未顯示。實線則代表兩個節點之間是直接呼叫的。

更多原創文章乾貨分享,請關注公眾號
  • Go 高效能系列教程:讀懂 pprof 生成的報告
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章