pprof簡介
pprof是go自身提供的工具鏈,可以用來做性能監控。pprof有兩個包:
- runtime/pprof
pprof的具體實現,所有類型的代碼都可以使用。如果不是Web應用程序,建議使用該包。 - net/http/pprof
對runtime/pprof包進行簡單封裝,并在http端口上暴露出來。適合Web應用程序使用。
pprof監控內容
pprof監控的內容項目入下表所示。
類型 | 描述 | 備注 |
---|---|---|
allocs | 內存分配情況的采樣信息 | 可以用瀏覽器打開,但可讀性不高 |
blocks | 阻塞操作情況的采樣信息 | 可以用瀏覽器打開,但可讀性不高 |
cmdline | 顯示程序啟動命令及參數 | 可以用瀏覽器打開,但可讀性不高 |
goroutine | 當前所有協程的堆棧信息 | 可以用瀏覽器打開,但可讀性不高 |
heap | 堆上內存使用情況的采樣信息 | 可以用瀏覽器打開,但可讀性不高 |
mutex | 鎖爭用情況的采樣信息 | 可以用瀏覽器打開,但可讀性不高 |
profile | CPU 占用情況的采樣信息 | 瀏覽器打開會下載文件 |
threadcreate | 系統線程創建情況的采樣信息 | 可以用瀏覽器打開,但可讀性不高 |
trace | 程序運行跟蹤信息 | 瀏覽器打開會下載文件 |
使用pprof進行監控
一下兩種使用pprof進行性能監控的方式只能生成監控信息文件,具體的分析需要使用go tool pprof [binary] file進行查看和分析。
非Web應用程序
非Web應用程序使用包runtime/pprof,生成監控文件。
下面示例進行CPU監控,并將監控數據存放在當前項目的pprof/profile_file/profile_file文件中。
import (
"log"
"os"
"path/filepath"
"runtime/pprof"
)
// 進行CPU監控
func CreateProfileFile() {
dir, err := os.Getwd()
if err != nil {
log.Fatalln("get current directory failed.", err)
}
fileName := filepath.Join(dir, "pprof", "profile_file", "profile_file")
f, _ := os.Create(fileName)
// start to record CPU profile and write to file `f`
_ = pprof.StartCPUProfile(f)
// stop to record CPU profile
defer pprof.StopCPUProfile()
// TODO do something
}
Web應用程序
Web應用程序使用包net/http/pprof,可以搭建Web服務器查看監控信息。通過http://locahost:6060/debug/pprof進行查看相關的監控信息文件。
import (
"log"
"net/http"
_ "net/http/pprof"
"os"
"runtime"
)
func main() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
log.SetOutput(os.Stdout)
runtime.GOMAXPROCS(1)
runtime.SetMutexProfileFraction(1)
runtime.SetBlockProfileRate(1)
go func() {
if err := http.ListenAndServe(":6060", nil); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
}
注意
如果你使用自定義的 Mux,則需要手動注冊一些路由規則:
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
pprof監控信息使用
golang原生自帶pprof工具的go tool pprof [binary] file命令進入交互式終端來排查應用程序的性能問題。其中,
binary
正在執行的二進制可執行程序,可選。file
pprof監控生成的文件。可以是具體的文件如profile.pprof,也可以是web站點的地址,如http://localhost:6060/debug/pprof/profile。
進入終端之后,排查性能問題的三個命令為:top
查看資源較高的調用。list
list 代碼片段查看問題代碼具體位置。-
web
在Web Browser上圖形化顯示當前的資源監控內容。需要事先安裝graphviz。
web命令的實際行為是產生一個 .svg文件,并調用系統里設置的默認打開 .svg 的程序打開它。如果系統里打開 .svg 的默認程序并不是瀏覽器(比如代碼編輯器),需要設置一下默認使用瀏覽器打開 .svg 文件。然后瀏覽器自動打開,可以看到:
示例block的監控信息
如果需要其他命令,可以在pprof交互式終端里輸入help查看其他命令的使用方法。例如,
svg
生成svg圖。pdf
生成pdf文件,顯示svg圖。png
生成png圖片,顯示svg圖。...
當然還有很多其他的命令和選項,請自行學習驗證。
pprof監控信息展示——火焰圖
火焰圖(Flame Graph)是 Bredan Gregg 創建的一種性能分析圖表,因為它的樣子近似火焰而得名。golang性能監控結果可以轉換成火焰圖來進行直觀展示。火焰圖 svg 文件可以通過瀏覽器打開,它展示調用圖的最大優點是火焰圖動態的——可以通過點擊每個方塊來分析它上層概況/下層詳細的內容。
火焰圖的調用順序從下到上,每個方塊代表一個函數,它上面一層表示這個函數會調用哪些函數,方塊的大小代表了占用資源值的多少(例如,CPU使用時間的長短,內存使用的大小等)。火焰圖的配色并沒有特殊的意義,默認的紅、黃配色是為了更像火焰而已。
生成火焰圖,有兩種方式:go-torch(golang version < 1.10)和golang原生的pprof(golang version < 1.10+的pprof集成了火焰圖功能)。
go-torch
go-torch是uber 開源的一個工具。go-torch可以直接讀取 golang 的監控數據文件,并生成一個火焰圖的 svg 文件。
go-torch工具使用非常簡單,最簡單的是使用go-torch的docker鏡像運行,無需安裝go-torch。
- 首先進行docker安裝(ubuntu)。其他操作系統的安裝參考codker安裝。
- 運行go-rorch鏡像 uber/go-torch 。
如果不知道相關命令,可以執行$ sudo docker run uber/go-torch -h查看go-torch的使用幫助。
$ sudo docker run uber/go-torch -h
Usage:
go-torch [options] [binary] <profile source>
pprof Options:
-u, --url= Base URL of your Go program (default:
http://localhost:8080)
--suffix= URL path of pprof profile (default: /debug/pprof/profile)
-b, --binaryinput= File path of previously saved binary profile. (binary
profile is anything accepted by
https://golang.org/cmd/pprof)
--binaryname= File path of the binary that the binaryinput is for, used
for pprof inputs
-t, --seconds= Number of seconds to profile for (default: 30)
--pprofArgs= Extra arguments for pprof
Output Options:
-f, --file= Output file name (must be .svg) (default: torch.svg)
-p, --print Print the generated svg to stdout instead of writing to
file
-r, --raw Print the raw call graph output to stdout instead of
creating a flame graph; use with Brendan Gregg's flame
graph perl script (see
https://github.com/brendangregg/FlameGraph)
--title= Graph title to display in the output file (default: Flame
Graph)
--width= Generated graph width (default: 1200)
--hash Colors are keyed by function name hash
--colors= set color palette. choices are: hot (default), mem, io,
wakeup, chain, java, js, perl, red, green, blue, aqua,
yellow, purple, orange
--cp Use consistent palette (palette.map)
--reverse Generate stack-reversed flame graph
--inverted icicle graph
Help Options:
-h, --help Show this help message
最重要的命令有五個:
可選參數選項 | 描述 | 默認值 | 備注 |
---|---|---|---|
-u, --url= | golang代碼的基礎URL——[scheme]://[host]:[port] | http://localhost:8080 | |
--suffix= | pprof profile文件URL路徑 | /debug/pprof/profile | |
-t, --seconds= | 執行profile的時間長度,單位是秒 | 30 | |
-f, --file= | 輸出文件的名稱 | torch.svg | 文件擴展名必須是 .svg |
-p, --print | 將生成的svg文件打印到標準輸出,而不是寫入文件 |
所有參數都是可選參數。如果沒有任何參數,默認情況下,會嘗試從http://localhost:8080/debug/pprof/profile 獲取監控數據。
例如,從服務器http://10.0.2.15:6060/debug/pprof/block獲取阻塞信息,并將生成的svg文件打印到標準輸出中,然后信息重定向保存到本地torch.svg文件。
$ sudo docker run uber/go-torch -u http://10.0.2.15:6060 --suffix=/debug/pprof/block -p > torch.svg
INFO[02:33:36] Run pprof command: go tool pprof -raw -seconds 30 http://10.0.2.15:6060/debug/pprof/block
INFO[02:33:36] Printing svg to stdout
第一次執行由于需要安裝go-torch相關依賴和鏡像,等待時間較長。
執行成功之后,本地會生成一個torch.svg文件。右鍵通過瀏覽器打開,可以看到火焰圖,如下圖所示:
使用go-torch的docker鏡像可以在windows操作系統使用。
注:當然了,可以將go-torch和FlameGraph工具分別安裝,然后執行go-torch命令。具體參數和go-torch鏡像執行-h顯示的參數相同。此處不再贅述。
使用golang的pprof查看火焰圖
使用go tool pprof可以在Web界面上查看所有類型的資源監控圖。
例如,使用pprof查看Web服務器的阻塞監控數據,并將結果展示在6061端口。通過http://localhost:6062/ui/flamegraph即可查看生成的火焰圖。
$ go tool pprof -http=:6061 http://localhost:6060/debug/pprof/block
Fetching profile over HTTP from http://localhost:6060/debug/pprof/block
Saved profile in /home/jerry/pprof/pprof.___go_build_main_go.contentions.delay.005.pb.gz
從執行命令的過程,可以看到pprof工具從http://localhost:6060/debug/pprof/block獲取監控數據,并保存到本地:/home/jerry/pprof/pprof.___go_build_main_go.contentions.delay.005.pb.gz。
然后對該文件進行分析,并啟動一個Web服務器:http://localhost:6061。一般會自動彈出一個瀏覽器并顯示結果——默認顯示的是graph。但是可以從第一行的菜單中切換View,選擇Flame Graph即可顯示火焰圖。