這是什么
想要進行性能優化,Go本身自帶的工具鏈就包含了性能分析工具,而且也非常棒,pprof就是Go性能分析的利器,它是Go語言自帶的包,有如下兩種:
- runtime/pprof:采集程序(非 Server)的運行數據進行分析
- net/http/pprof:采集 HTTP Server 的運行時數據進行分析,這個其實在上面的功能中包了一層提供了http接口。
pprof用於可視化和性能分析的工具,pprof 以 profile.proto 讀取分析樣本的集合,並生成報告以可視化並幫助分析數據(支持文本和圖形報告)
這個文件是一個ProtocolBuffer v3的描述文件,它描述了一組callstack和 symbolization信息,作用是表示統計分析的一組采樣的調用棧,是很常見的 stacktrace 配置文件格式
使用方式
Report generation:報告生成,直接生成一個文件,解析這個文件得到結果
Interactive terminal use:交互式終端使用,實時反饋,監控,需要開發人員輸入指令,根據輸入的指令返回想要的信息。
Web interface:Web 界面,實時反饋,監控,對開發人員友好。很方便,直觀的獲取和統計需要的數據。
能做什么
CPU Profiling: CPU分析,按照一定的頻率采集所監聽的應用程序的CPU使用情況,可確定應用程序在主動消耗 CPU 周期時花費時間的位置。
Memory Profiling:內存分析,在應用程序堆棧分配時記錄跟蹤,用於監視當前和歷史內存使用情況,檢查內存泄漏情況。
Block Profiling:阻塞分析,記錄goroutine阻塞等待同步的位置
Mutex Profiling:互斥鎖分析,報告互斥鎖的競爭情況
一個小Demo來解釋
import (
"net/http"
_ "net/http/pprof"
)
func PprofWeb() {
err := http.ListenAndServe(":9909", nil)
if err != nil {
panic(err)
}
}
web界面使用
啟動這段代碼后,訪問 http://localhost:9909/debug/pprof/ ,就可以看到監控頁面了,截圖信息如下,我們對這些進行一下解釋。
allocs:所有過去內存分配的采樣
block:導致同步原語阻塞的堆棧跟蹤
cmdline:當前程序的命令行調用
goroutine:所有當前goroutine的堆棧跟蹤
heap:活動對象的內存分配的采樣。在獲取堆樣本之前,可以指定gc GET參數來運行gc。
metux:爭用互斥鎖持有者的堆棧跟蹤
profile:CPU配置文件。您可以在seconds GET參數中指定持續時間。獲取配置文件后,使用go tool pprof命令調查配置文件
threadcreate:導致創建新操作系統線程的堆棧跟蹤
trace:當前程序的執行軌跡。您可以在seconds GET參數中指定持續時間。獲取跟蹤文件后,使用go tool trace命令調查跟蹤
交互式終端使用
控制台輸入如下命令,這個命令的作用是追蹤上面代碼60秒內CPU的消耗情況,執行該命令后,需要等待60秒(這個時間可自己調整),60秒到達后默認進入pprof交互式命令行中,可輸入help命令查看pprof的使用幫助
go tool pprof http://localhost:9909/debug/pprof/profile?seconds=60
我們看下面圖片,命令執行后,過了10秒鍾進入交互式控制台,我輸入了top10,代表意思是顯示前10個消耗CPU較多的方法,圖中的flat,sum,cum是什么含義呢,接下來解釋一下。
flat:給定函數上的運行耗時
flat% :給定函數上的CPU運行耗時占比
sum% :給定函數累積使用CPU總比例
cum :當前函數加上它之前的調用運行總耗時
cum% :當前函數加上他之前的調用CPU運行耗時占比
還有其它很多的命令比如 list,使用 list 函數名 命令查看具體的函數分析,同樣的,下面的命令行可以查看堆內存,阻塞,鎖的使用情況
go tool pprof http://localhost:9099/debug/pprof/heap
go tool pprof http://localhost:9099/debug/pprof/block
go tool pprof http://localhost:9099/debug/pprof/mutex
可視化界面使用
在上面的web界面中我們可以看到一行profile文字,點擊這個文字可以下載一個profile文件,下載完成之后。我們在這個文件所在目錄運行如下命令,有兩種方式
go tool pprof profile文件名, 此時會進入一個交互式控制台,輸入命令 web會產生一個svg文件,程序回啟動瀏覽器自動打開這個文件,即可進入可視化界面。我們也可以在上面CPU分析中的控制台中以同樣的方式進入可視化界面。
go tool pprof -http=:8080 profile文件名 ,此時瀏覽器會默認打開localhost:8080訪問 ,建議使用這種方式,獲取更好體驗。
如果出現下面錯誤,你需要安裝一個軟件Graphviz,安裝地址如下,這是一個圖形可視化軟件,安裝完成之后配置環境變量
https://graphviz.gitlab.io/_pages/Download/Download_windows.html
Failed to execute dot. Is Graphviz installed? Error: exec: "dot": executable file not found in %PATH%
如下圖,展示CPU的在各個方法上的運行時間,關於圖形的說明: 每個框代表一個函數,理論上框的越大表示占用的CPU資源越多。 方框之間的線條代表函數之間的調用關系。 線條上的數字表示cpu執行時間。 方框中的第一行數字表示當前函數占用CPU的百分比,第二行數字表示當前函數累計占用CPU的百分比。
火焰圖
使用火焰圖需要手動安裝Pprof原生工具,這是google提供的一個工具,記住google和Go官方不是一個概念。
go get -u github.com/google/pprof
啟動火焰圖可視化工具
pprof -http=:8080 profile文件名
訪問web地址 localhost:8080,如果上面的命令不加-http=:8080,則默認進入交互式控制台,輸入web命令,生成一個文件自動啟動瀏覽器自動打開,火焰圖明顯比上面Go官方的可視化界面要精致許多。
如何觀察下面的火焰圖呢?Y軸表示調用棧,每一層都是一個函數,調用棧越深火焰就越高,最底部是正在執行的函數,上面是它的父函數,X軸表示這個函數的抽樣數,如果一個函數在X軸占的越寬,代表抽樣數越高,執行CPU的時間越長,注意,X軸不代表時間,而是所有的調用棧合並后,按字母順序排列的.
火焰圖就是看頂層的哪個函數占據的寬度最大。只要有"平頂"(plateaus),就表示該函數可能存在性能問題
uber 也開源了一個火焰圖工具,github地址如下,教程很多,大家可以了解了解。
github.com/uber/go-torch,
對非web程序的性能分析
截至目前,上面我們都是對一個web應用程序進行性能檢測分析,用到的都是http接口形式訪問,那么一個非web程序應該監測性能呢?如果你仔細觀察你會發現性能分析的本質就是對profile文件進行分析,所以我們需要在一個非web應用程序中生成一個profile文件出來,這樣就可以通過go tool pprof工具分析這個文件了
在runtime/pprof 提供了很多方法用來統計程序運行過程中CPU和內存的消耗情況,下面我們一起實踐一下。
下面這段代碼獲取CPU的profile文件,會在當前目錄下生成一個cpu.prof文件,之后我們可以通過go tool prof -http=:8080 cpu.prof 這個命令用瀏覽器來查看cpu的使用情況
func PProfCPUApplication() {
f, _ := os.Create("./cpu.prof")
pprof.StartCPUProfile(f)
for i := 1; i < 3000; i++ {
time.Sleep(3 * time.Millisecond)
RandomInt(10, 50)
}
pprof.StopCPUProfile()
f.Close()
}
下面這段代碼獲取內存的profile文件,會在當前目錄下生成一個mem.prof文件,之后我們可以通過go tool prof -http=:8080 mem.prof 這個命令用瀏覽器來查看內存的使用情況
func PProfMemApplication() {
f, _ := os.Create("./mem.prof")
for i := 1; i < 3000; i++ {
time.Sleep(3 * time.Millisecond)
RandomInt(10, 50)
}
pprof.WriteHeapProfile(f)
f.Close()
}
在如何用好Go的測試黑科技一文中也說到可以用go test在測試時使用指定參數生成CPU和內存的profile文件。
go test -bench . -cpuprofile= cpu.prof
go test -bench . -memprofile= mem.prof
對Pprof的簡單介紹就到這里了,有關更多PProf的性能分析大家可以更深入的研究,一起交流。