1. 程式人生 > >Go效能分析大殺器PPROF

Go效能分析大殺器PPROF

#### 這是什麼 想要進行效能優化,Go本身自帶的工具鏈就包含了效能分析工具,而且也非常棒,pprof就是Go效能分析的利器,它是Go語言自帶的包,有如下兩種: 1. runtime/pprof:採集程式(非 Server)的執行資料進行分析 2. 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來解釋 ```go import ( "net/http" _ "net/http/pprof" ) func PprofWeb() { err := http.ListenAndServe(":9909", nil) if err != nil { panic(err) } } ``` ##### web介面使用 啟動這段程式碼後,訪問 http://localhost:9909/debug/pprof/ ,就可以看到監控頁面了,截圖資訊如下,我們對這些進行一下解釋。 ![](https://img2020.cnblogs.com/blog/706455/202003/706455-20200309180635416-602112268.png) 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執行耗時佔比 ![](https://img2020.cnblogs.com/blog/706455/202003/706455-20200309180648960-575488134.png) 還有其它很多的命令比如 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的百分比。 ![](https://img2020.cnblogs.com/blog/706455/202003/706455-20200309180706323-1530333533.png) #### 火焰圖 使用火焰圖需要手動安裝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),就表示該函式可能存在效能問題 ![](https://img2020.cnblogs.com/blog/706455/202003/706455-20200309180724812-1871863865.png) 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的使用情況 ```go 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 這個命令用瀏覽器來檢視記憶體的使用情況 ```go 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的效能分析大家可以更深入的研究,一起交流。

![](https://img2018.cnblogs.com/blog/706455/201909/706455-20190911210708072-261554801.jpg)

<