天天看點

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

文章目錄

  • 一、什麼是pprof
  • 二、怎麼使用pprof
    • 1. 工具型應用
    • 2. 服務型應用
  • 三、`pprof`資料分析
    • CPU Profiling
      • top指令排序展示
      • web指令生成圖示
      • list指令分析函數
      • 堆記憶體分析示例
  • 四、pprof資料分析類型彙總
  • 參考連接配接

一、什麼是pprof

pprof是Go官方提供的性能分析工具,可以分析程式的運作情況,并且提供可視化的功能。prof是profile(畫像)的縮寫,使用pprof可以分析以下幾種名額資料:

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接
  • allocs

    :程式啟動之後記憶體配置設定的情況
  • block

    :導緻阻塞操作的一些堆棧跟蹤資訊
  • cmdline

    :目前程式啟動的指令行
  • goroutine

    :所有目前

    goroutine

    的堆棧跟蹤資訊
  • heap

    :程式在目前堆上記憶體配置設定的情況
  • mutex

    :鎖資源的競争的堆棧資訊
  • profile

    CPU profile

    檔案。可以在

    debug/pprof?seconds=x秒

    GET

    參數中指定持續時間。擷取

    pprof

    檔案後,使用

    go tool pprof x.prof

    指令分析

    pprof

    檔案。
  • threadcreate

    :系統線程的使用情況
  • trace

    :目前系統的代碼執行的鍊路情況

使用

pprof

工具主要分析以下幾種名額:

  • CPU Profiling

    CPU

    分析,按照一定的頻率采集所監聽的應用程式

    CPU

    (含寄存器)的使用情況,可确定應用程式在主動消耗

    CPU

    周期時花費時間的位置
  • Memory Profiling

    :記憶體分析,在應用程式進行堆配置設定時記錄堆棧跟蹤,用于監視目前和曆史記憶體使用情況,以及檢查記憶體洩漏
  • Block Profiling

    :阻塞分析,記錄

    goroutine

    阻塞等待同步(包括定時器通道)的位置
  • Mutex Profiling

    :互斥鎖分析,報告互斥鎖的競争情況。

當程式存在記憶體或者

CPU

飙升的情況時,我們可以通過

pprof

工具來查詢問題出現的根源。

二、怎麼使用pprof

pprof包含兩個相關的庫:

  1. runtime/pprof

    主要應用于工具型應用。包含腳本、定時任務等。

    如:對于隻跑一次的程式,例如每天隻跑一次的離線預處理程式,調用 pprof 包提供的函數,手動開啟性能資料采集

  2. net/http/pprof

    主要應用于服務型應用。包含HTTP服務,GRPC服務等。

    如:對于線上服務,對于一個 HTTP Server,通路 pprof 提供的 HTTP 接口,獲得性能資料。當然,實際上這裡底層也是調用的

    runtime/pprof

    提供的函數,封裝成接口對外提供網絡通路。

1. 工具型應用

工具型應用主要使用

runtime/pprof

包實作性能分析。

func main() {
	// --- cpu 分析示例 start---
	// 建立cpu分析檔案
	fc, err := os.Create("./cpu.prof")
	if err != nil {
		fmt.Println("create cpu.prof err:", err.Error())
		return
	}
	defer fc.Close()

	// 開始分析cpu
	err = pprof.StartCPUProfile(fc)
	if err == nil {
		defer pprof.StopCPUProfile()
	}
	// --- cpu 分析示例 end---
	
	var count int
	for i := 0; i < 10000; i++ {
		count++
	}

	// --- 記憶體 分析示例 start---
	fm, err := os.Create("./memory.prof")
	if err != nil {
		fmt.Println("create memory.prof err:", err.Error())
		return
	}
	defer fm.Close()

	// 開始分析記憶體
	err = pprof.WriteHeapProfile(fm)
	if err != nil {
		fmt.Println("write heap prof err:", err.Error())
		return
	}
	// --- 記憶體 分析示例 end---

	for i := 0; i < 10000; i++ {
		count++
	}
	fmt.Println("do finish......count:", count)
}
           

執行

go run main.go

後,在代碼目錄下,可以看到生成了

cpu.prof

memory.prof

檔案。

通過執行

go tool pprof ./memory.prof

或者

go tool pprof -http=:8888 ./memory.prof

進入指令行模式或者web頁面進行性能分析。

執行

go tool pprof ./memory.prof

進入指令行:

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

執行

go tool -http=:8888 pprof ./memory.prof

可進入

web

頁面,更友善檢視:

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

頁面展示效果:

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

SAMPLE各個标簽的含義解釋:

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

2. 服務型應用

對于服務類型的應用,主要在服務内部匿名引入

net/http/pprof

包,然後通過

HTTP

通路

pprof

頁面。

匿名引入方式為:

import _ "net/http/pprof"

package main

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

func main() {
	http.HandleFunc("/", hello)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Println("ListenAndServe Err:", err.Error())
		return
	}
}

func hello(resp http.ResponseWriter, req *http.Request) {
	fmt.Fprintln(resp, "Hello World, Are You OK?")
}
           

執行

http://localhost:8080/debug/pprof/

可以看到畫像資訊:

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

但是需要注意,如果HTTP服務不是通過

http.ListenAndServe(":8080", nil)

啟動的,而是指定第二個參數啟動的話,需要自己注冊

pprof

路由。

net/http/pprof/pprof.go

的官方源碼注釋中也提到此種情況:

If you are not using DefaultServeMux, you will have to register handlers with the mux you are using.

如果您不使用DefaultServeMux,則必須向所使用的多路複用器注冊pprof處理程式

http.ListenAndServe函數可以傳遞handler,如果handler不為nil,則說明研發自定義了 ServeMux,否則用的是預設DefaultServeMux

net/http/pprof

包中,有

init

函數

func init() {
   http.HandleFunc("/debug/pprof/", Index)
   http.HandleFunc("/debug/pprof/cmdline", Cmdline)
   http.HandleFunc("/debug/pprof/profile", Profile)
   http.HandleFunc("/debug/pprof/symbol", Symbol)
   http.HandleFunc("/debug/pprof/trace", Trace)
}
           

是以如果使用預設

ServeMux

,則不需要注冊,但是如果使用自定義的

ServeMux

,則需要增加注冊後,才能擷取到

pprof

// 自己注冊這幾個函數
r.HandleFunc("/debug/pprof/", pprof.Index)
r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
r.HandleFunc("/debug/pprof/profile", pprof.Profile)
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
           

另外一種啟動

pprof

的方式在生産環境中更加常用:通過協程另起一個

HTTP

服務,單獨用作

pprof

分析:

func RegisterProf() {
	go func() {
		if err := http.ListenAndServe(":6060", nil); err != nil {
			panic("pprof server start error: " + err.Error())
		}
	}()
}
           

三、

pprof

資料分析

GO

官方提供了

go tool pprof

工具來幫助我們分析

pprof

生成的資料檔案。

使用

go tool pprof

分析資料,主要有兩種模式:

  1. 指令行互動模式

    go tool pprof [file_pprof|url_pprof]

  2. web頁面模式

    go tool pprof -http=:6666 [file_pprof|url_pprof]

    其中,

    file_pprof

    表示生成的

    prof

    分析檔案,如

    cpu.prof

    url_pprof

    表示遠端服務開啟的

    pprof

    通路,如

    http://localhost:8080/debug/pprof/profile

進入指令行互動模式後,可以使用

help

檢視所有子指令,使用

help <cmd|option>

檢視子指令使用方法。如

help、help top

CPU Profiling

浏覽器通路

/debug/pprof/profile

會自動進行

CPU profiling

,預設持續 30s,并生成一個檔案供下載下傳,可以通過帶參數

?seconds=60

進行

60

秒的資料采集。

為了模拟請求,使用ab進行壓測,

ab -k -c 1 -t 180 -n 100000000 http://localhost:8080/hello

執行

go tool pprof http://localhost:8080/debug/pprof/profile

後,預設需要等30s才會顯示互動

top指令排序展示

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

每一行表示一個函數的資訊,列資訊字段解釋:

  • flat

    :函數在 CPU 上運作的時間
  • flat%

    :函數在CPU上運作時間的百分比
  • sum%

    :是從第一行到目前行所有函數累加使用 CPU 的比例,如第二行sum=53.85=30.77+23.08
  • cum

    :這個函數以及子函數運作所占用的時間,應該大于等于flat
  • cum%

    :這個函數以及子函數運作所占用的比例,應該大于等于flat%
  • 最後一列

    :函數的名字

web指令生成圖示

在互動模式下輸入 web,會自動生成一個 svg 檔案,并跳轉到浏覽器打開。

改功能需要安裝graphviz後才能使用,安裝方法https://shidawuhen.github.io/2020/02/08/go-callvis/ 。
Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

圖中每個方框對應應用程式運作的一個函數,方框越大代表函數執行的時間越久(函數執行時間會包含它調用的子函數的執行時間,但并不是正比的關系);方框之間的箭頭代表着調用關系,箭頭上的數字代表被調用函數的執行時間。

具體細節可以參考:https://github.com/google/pprof/tree/master/doc#interpreting-the-callgraph

runtime netpoll

為例:

箭頭上的

230ms

表示該函數總共的執行時間,包含自身和下遊所有子節點;

方框中的

10ms

表示自身的執行時間;

方框中的

2.70%

表示自身執行時間在該函數總共執行時間的占比在總時間中的占比:

2.70 = (10/230)*62.16

方框中的

62.16%

表示總時間占比,即整個程式耗時占比。

list指令分析函數

确定出哪個函數耗時之後,可以用

pprof

分析函數中的哪一行導緻的耗時,使用子指令:list 函數名。

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

堆記憶體分析示例

記憶體配置設定既可以發生在堆上也可以在棧上。堆上配置設定的記憶體需要垃圾回收或者手動回收(對于沒有垃圾回收的語言,例如 C++),棧上的記憶體則通常在函數退出後自動釋放。

Go 語言通過逃逸分析會将盡可能多的對象配置設定到棧上,以使程式可以運作地更快。

這裡說明一下,有兩種記憶體分析政策:一種是目前的(這一次采集)記憶體或對象的配置設定,稱為

inuse

;另一種是從程式運作到現在所有的記憶體配置設定,不管是否已經被

gc

過了,稱為

alloc

As mentioned above, there are two main memory analysis strategies with pprof. One is around looking at the current allocations (bytes or object count), called inuse. The other is looking at all the allocated bytes or object count throughout the run-time of the program, called alloc. This means regardless if it was gc-ed, a summation of everything sampled.

加上 -sample_index 參數後,可以切換記憶體分析的類型:

go tool pprof -sample_index=alloc_space http://localhost:8080/debug/pprof/heap

或者

go tool pprof -alloc_space http://localhost:8080/debug/pprof/heap

四種标簽:

Go性能分析工具pprof詳解一、什麼是pprof二、怎麼使用pprof三、pprof資料分析四、pprof資料分析類型彙總參考連接配接

四、pprof資料分析類型彙總

其他資料的分析和

CPU

的基本一緻。下面列舉所有的分類:

http://localhost:8080/debug/pprof/ :擷取概況資訊,即本文第一張圖的資訊
go tool pprof http://localhost:8080/debug/pprof/allocs : 分析記憶體配置設定
go tool pprof http://localhost:8080/debug/pprof/block : 分析堆棧跟蹤導緻阻塞的同步原語
go tool pprof http://localhost:8080/debug/pprof/cmdline : 分析指令行調用的程式,web下調用報錯
go tool pprof http://localhost:8080/debug/pprof/goroutine : 分析目前 goroutine 的堆棧資訊
go tool pprof http://localhost:8080/debug/pprof/heap : 分析目前活動對象記憶體配置設定
go tool pprof http://localhost:8080/debug/pprof/mutex : 分析堆棧跟蹤競争狀态互斥鎖的持有者
go tool pprof http://localhost:8080/debug/pprof/profile : 分析一定持續時間内CPU的使用情況
go tool pprof http://localhost:8080/debug/pprof/threadcreate : 分析堆棧跟蹤系統新線程的建立
go tool pprof http://localhost:8080/debug/pprof/trace : 分析追蹤目前程式的執行狀況
           

參考連接配接

  1. 一文搞懂pprof
  2. 深度解密Go語言之 pprof
  3. go性能分析工具pprof
  4. Go語言:利用pprof工具排查記憶體洩漏的示例
  5. Go語言:利用pprof工具查找goroutine(協程)洩漏的示例
  6. go 程式性能調優 pprof 的使用

繼續閱讀