pprof CPU性能測試


基本介紹

pprof 是在做性能優化前的性能分析工具。

安裝: go get -u github.com/google/pprof

分析工具

go tool pprof 是命令行指令,用於分析 Profiling 數據,源數據可以是 http 地址,也可以是已經 dump 下當 profile 文件;查看模式可以命令行交互模式,也可以是瀏覽器模式(-http 參數)。

兩種應用

  • 服務型應用 _ "net/http/pprof" 包,專用於采集 web 服務 運行數據的分析。即在運行的服務中通過 API 調用取數據。
  • 工具型應用 "runtime/pprof" 包,專用於采集 應用程序 運行數據的分析。通過代碼手動添加收集命令。

服務型應用場景中因為應用要一直提供服務。所以 pprof 是通過 API 訪問來獲取,pprof 使用了默認的 http.DefaultServeMux 掛在這些 API 接口。開發者也可以手動注冊路由規則掛載 API,如 r.HandleFunc("/debug/pprof/debugopen", openFunc)

工具性應用是一個提供特定功能使用的工具,使用完就會退出進程的應用。開發者手動控制把 profile 文件保存到報告文件中。

封裝了接口可以調用,如要進行 CPU Profiling,則調用 pprof.StartCPUProfile(w io.Writer) 寫入到 w 中,停止時調用 StopCPUProfile();要獲取內存數據,直接使用 pprof.WriteHeapProfile(w io.Writer) 函數則可。

可以做?

可以做( $host/debug/pprof/$type, $type 即下方列表的英文單詞):

  • CPU 分析(profile): 你可以在 url 上用 seconds 參數指定抽樣持續時間(默認 30s),你獲取到概覽文件后可以用 go tool pprof 命令調查這個概覽
  • 內存分配(allocs): 所有內存分配的抽樣
  • 阻塞(block): 堆棧跟蹤導致阻塞的同步原語
  • 命令行調用(cmdline): 命令行調用的程序
  • goroutine: 當前 goroutine 的堆棧信息
  • 堆(heap): 當前活動對象內存分配的抽樣,完全也可以指定 gc 參數在對堆取樣前執行 GC
  • 互斥鎖(mutex): 堆棧跟蹤競爭狀態互斥鎖的持有者
  • 系統線程的創建(threadcreate): 堆棧跟蹤系統新線程的創建
  • trace: 追蹤當前程序的執行狀況. 你可以用 seconds 參數指定抽樣持續時間. 你獲取到 trace 概覽后可以用 go tool pprof 命令調查這個 trace

基本使用

(初學,以下暫時均以 net/http/pprof 使用為例)

  1. 編寫 Demo 文件 demo.go,運行這個文件
package main

import (
    "log"
    "net/http"
    _ "net/http/pprof"
)

func main() {
    go func() {
        for {
            log.Println(Add("Hello world"))
        }
    }()

    http.ListenAndServe("0.0.0.0:6060", nil)
}

var datas []string

func Add(str string) string {
    data := []byte(str)
    sData := string(data)
    datas = append(datas, sData)

    return sData
}

通過 Web API 分析

  • 訪問 http://localhost:6060/debug/pprof/ 頁面,可以看到總覽
  • 點擊其中的鏈接,可以看到各部分的概覽

注:網頁點擊一些鏈接會下載文件,這些文件應該是需要專用工具才能打開查看分析,如 profile;而且默認采樣時長 30s

通過 dump 文件進行分析

通過 dump 文件進行分析可以在命令行中交互式分析,也可以通過瀏覽器進行可視化分析。

  • 通過執行命令 go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60 會進行 60s 內進行采樣(默認 30s),並進入 命令行交互模式

    $ go tool pprof http://localhost:6060/debug/pprof/profile
    Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile
    Saved profile in C:\Users\xxxxxx\pprof\pprof.samples.cpu.003.pb.gz
    Type: cpu
    Time: Jun 17, 2020 at 3:25pm (CST)
    Duration: 30.14s, Total samples = 31.64s (104.96%)
    Entering interactive mode (type "help" for commands, "o" for options)
    (pprof)
    

可輸入 help 查看可用命令,輸入 o 查看可用選項。沒多用這里就不再介紹。

CPU profile 的 top 命令

在 CPU profile 交互頁面輸入 topN 可以查看 top N 的概況(N 可省略,默認為 10)

(pprof) top
Showing nodes accounting for 29.92s, 94.56% of 31.64s total
Dropped 117 nodes (cum <= 0.16s)
Showing top 10 nodes out of 33
      flat  flat%   sum%        cum   cum%
    28.52s 90.14% 90.14%     28.58s 90.33%  runtime.cgocall
     0.81s  2.56% 92.70%      0.82s  2.59%  runtime.stdcall1
     0.24s  0.76% 93.46%      0.25s  0.79%  runtime.stdcall3
     0.16s  0.51% 93.96%     29.10s 91.97%  internal/poll.(*FD).writeConsole
     0.05s  0.16% 94.12%     29.28s 92.54%  internal/poll.(*FD).Write
     0.04s  0.13% 94.25%      0.18s  0.57%  runtime.findrunnable
     0.03s 0.095% 94.34%      0.18s  0.57%  runtime.mallocgc
     0.03s 0.095% 94.44%      0.25s  0.79%  runtime.mcall
     0.02s 0.063% 94.50%     29.49s 93.20%  log.(*Logger).Output
     0.02s 0.063% 94.56%     29.71s 93.90%  log.Println
(pprof)

信息:

  • 顯示的節點在總共 31.64s 的抽樣中,占 29.92s,比例 94.56%
  • 在 33 個樣本中顯示了 top 10
  • 列表解釋(cum: cumulative 堆積的)
    • flat: 在給定函數上運行耗時
    • flat%: 在給定函數上運行耗時總比例
    • sum%: 給定函數 累計 使用 CPU 總比例
    • cum: 當前函數 以及包含子函數 的調用運行總耗時
    • cum%: 同上的 CPU 運行耗時總比例
    • 最后一列為函數名稱

heap profile 的 top 命令

go tool pprof http://localhost:6060/debug/pprof/heap

$ go tool pprof http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profile in C:\Users\xxxxxx\pprof\pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz
Type: inuse_space
Time: Jun 17, 2020 at 3:52pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)
(pprof) top
Showing nodes accounting for 10.04GB, 100% of 10.04GB total
      flat  flat%   sum%        cum   cum%
   10.04GB   100%   100%    10.04GB   100%  main.Add
         0     0%   100%    10.04GB   100%  main.main.func1
(pprof)

  • inuse_space: 常駐內存占用情況
  • alloc_objects: 內存臨時分配情況

啟用可視化界面進行分析

需要安裝 graphviz,參考:Graphviz安裝及簡單使用

  • 方式一: go tool pprof -http=:8080 cpu.prof,通過 -http 參數
  • 方式二: go tool pprof cpu.prof,然后在交互頁面輸入 web [funcName] 命令(函數調用圖生成 svg 文件並用瀏覽器查看)

看懂這些菜單中的信息很重要,你可以知道中這個頁面能做到什么,本人中調查過程中就沒有注意這個問題,浪費了很多時間,到后面才后知后覺。

 
pprof菜單項
- VIEW 看各種視圖
  - Top:主要看占用內存當排名信息
  - Graph:主要看調用關系圖,並且通過框框的粗細、顏色當深淺、線的實虛、以及數字信息包括執行時間和占比
  - Flame Graph:火焰圖,要看寬度和深度,heap 中寬度表明內存占用大小,
  - Peek
  - Source
  - Disassemble
- SAMPLE:采樣信息,包括申請對象、申請空間、占用對象、占用空間的信息
- REFINE:可以精細化視圖中的信息
  - Focus:聚焦在選中元素的上下游元素
  - Ignore:忽略選中當元素,包含其后繼元素
  - Hide:隱藏選中當元素,但不會隱藏其后繼元素
  - Show:只顯示選中的元素,不包含后繼元素
  - Show from:從選中當某一個元素開始,只列出其后繼元素
- CONFIG:能將當前已精細化的頁面保存起來

對比兩個文件差異

可以使用 go tool pprof -http=:9092 -base 0713_1544_heap 0715_1439_heap 對比兩個文件,並通過瀏覽器打開。很實用。

火焰圖🔥

火焰圖,調用順序是從上到下(有些是從下到上,如火焰一般),每一塊代表一個函數,越大代表占用 CPU 時間越長。

點擊塊深入分析。

刨析火焰圖,參考如何讀懂火焰圖?

  • 火焰圖是對系統調用棧進行抽樣調查
  • 一般采樣記錄信息有三個參數:采樣的進程號、采樣的頻率(每秒采樣多少次,通常 99 次)、采樣持續時間
  • 如,對某 一個進程調用棧 進行采樣,每秒 99 次(Hz)、持續 30s。如果這個服務器有 16 個 CPU,就能采集到 99 * 30 * 16 = 47520 個調用棧信息
  • 將調用棧信息組裝成火焰圖
  • 火焰圖 Y 軸表示調用棧,每一個 都是一個函數。調用棧越深,火焰越高。火焰頂端是正在執行的函數,底端是父函數(有些火焰是正的,有些是倒的)
  • 火焰圖 X 軸表示抽樣次數。如果一個函數越寬,就表示被抽到的次數越多,執行時間越長。
  • 注意:X 軸不表示時間先后順序,而是所有調用棧合並后,按字母順序排列的。
  • 火焰圖的顏色表示 CPU 的繁忙程度。
  • 火焰圖就是看頂層那個函數最寬。若有“平頂”(plateaus),就很有可能存在性能問題。
  • 火焰圖是 SVG 圖(Scalable Vector Graphics 可伸縮的矢量圖形參考),可以很方便得進行互動。

火焰圖局限:

  • 調用棧過深時,某些系統只返回前面一部分(如前 10 層)
  • 函數名缺失時,只能用內存地址來表示(如匿名函數)

通過 test 用例也可以生產 profile 文件

編寫 test 用例,demo_test.go:

package main

import "testing"

const url = "hello world"

func TestAdd(t *testing.T) {
    s := Add(url)
    if s == "" {
        t.Errorf("Test.Add error")
    }
}

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(url)
    }
}

執行測試 go test -bench=. -cpuprofile=cpu.prof 及輸出:

$ go test -bench=. -cpuprofile=cpu.prof
goos: windows
goarch: amd64
pkg: awesomeProject/pprof
BenchmarkAdd-12         13364784                88.3 ns/op
PASS
ok      awesomeProject/pprof    1.828s

參數解釋:

  • -bench: 通過 go help testflag 查看,按通配運行 benchmarks
  • -cpuprofile: 指定 CPU profiling 的保存文件
  • -memprofile: 指定 Memory profiling 的保存文件

結果在本目錄生成了 cpu.prof 文件



作者:Robin92
鏈接:https://www.jianshu.com/p/f4690622930d
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM