原文地址:Golang 大殺器之性能剖析 PProfhtml
寫了幾噸代碼,實現了幾百個接口。功能測試也經過了,終於成功的部署上線了node
結果,性能不佳,什麼鬼?😭git
想要進行性能優化,首先矚目在 Go 自身提供的工具鏈來做爲分析依據,本文將帶你學習、使用 Go 後花園,涉及以下:github
pprof 是用於可視化和分析性能分析數據的工具golang
pprof 以 profile.proto 讀取分析樣本的集合,並生成報告以可視化並幫助分析數據(支持文本和圖形報告)web
profile.proto 是一個 Protocol Buffer v3 的描述文件,它描述了一組 callstack 和 symbolization 信息, 做用是表示統計分析的一組採樣的調用棧,是很常見的 stacktrace 配置文件格式性能優化
咱們將編寫一個簡單且有點問題的例子,用於基本的程序初步分析app
(1)demo.go,文件內容:函數
package main import ( "log" "net/http" _ "net/http/pprof" "github.com/EDDYCJY/go-pprof-example/data" ) func main() { go func() { for { log.Println(data.Add("https://github.com/EDDYCJY")) } }() http.ListenAndServe("0.0.0.0:6060", nil) }
(2)data/d.go,文件內容:工具
package data var datas []string func Add(str string) string { data := []byte(str) sData := string(data) datas = append(datas, sData) return sData }
運行這個文件,你的 HTTP 服務會多出 /debug/pprof 的 endpoint 可用於觀察應用程序的狀況
查看當前總覽:訪問 http://127.0.0.1:6060/debug/pprof/
/debug/pprof/ profiles: 0 block 5 goroutine 3 heap 0 mutex 9 threadcreate full goroutine stack dump
這個頁面中有許多子頁面,我們繼續深究下去,看看能夠獲得什麼?
$HOST/debug/pprof/profile
,默認進行 30s 的 CPU Profiling,獲得一個分析用的 profile 文件$HOST/debug/pprof/block
,查看致使阻塞同步的堆棧跟蹤$HOST/debug/pprof/goroutine
,查看當前全部運行的 goroutines 堆棧跟蹤$HOST/debug/pprof/heap
,查看活動對象的內存分配狀況$HOST/debug/pprof/mutex
,查看致使互斥鎖的競爭持有者的堆棧跟蹤$HOST/debug/pprof/threadcreate
,查看建立新OS線程的堆棧跟蹤(1)go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60
$ go tool pprof http://localhost:6060/debug/pprof/profile\?seconds\=60 Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=60 Saved profile in /Users/eddycjy/pprof/pprof.samples.cpu.007.pb.gz Type: cpu Duration: 1mins, Total samples = 26.55s (44.15%) Entering interactive mode (type "help" for commands, "o" for options) (pprof)
執行該命令後,需等待 60 秒(可調整 seconds 的值),pprof 會進行 CPU Profiling。結束後將默認進入 pprof 的交互式命令模式,能夠對分析的結果進行查看或導出。具體可執行 pprof help
查看命令說明
(pprof) top10 Showing nodes accounting for 25.92s, 97.63% of 26.55s total Dropped 85 nodes (cum <= 0.13s) Showing top 10 nodes out of 21 flat flat% sum% cum cum% 23.28s 87.68% 87.68% 23.29s 87.72% syscall.Syscall 0.77s 2.90% 90.58% 0.77s 2.90% runtime.memmove 0.58s 2.18% 92.77% 0.58s 2.18% runtime.freedefer 0.53s 2.00% 94.76% 1.42s 5.35% runtime.scanobject 0.36s 1.36% 96.12% 0.39s 1.47% runtime.heapBitsForObject 0.35s 1.32% 97.44% 0.45s 1.69% runtime.greyobject 0.02s 0.075% 97.51% 24.96s 94.01% main.main.func1 0.01s 0.038% 97.55% 23.91s 90.06% os.(*File).Write 0.01s 0.038% 97.59% 0.19s 0.72% runtime.mallocgc 0.01s 0.038% 97.63% 23.30s 87.76% syscall.Write
最後一列爲函數名稱,在大多數的狀況下,咱們能夠經過這五列得出一個應用程序的運行狀況,加以優化 🤔
(2)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 /Users/eddycjy/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.008.pb.gz Type: inuse_space Entering interactive mode (type "help" for commands, "o" for options) (pprof) top Showing nodes accounting for 837.48MB, 100% of 837.48MB total flat flat% sum% cum cum% 837.48MB 100% 100% 837.48MB 100% main.main.func1
(3) go tool pprof http://localhost:6060/debug/pprof/block
(4) go tool pprof http://localhost:6060/debug/pprof/mutex
這是使人期待的一小節。在這以前,咱們須要簡單的編寫好測試用例來跑一下
(1)新建 data/d_test.go,文件內容:
package data import "testing" const url = "https://github.com/EDDYCJY" 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) } }
(2)執行測試用例
$ go test -bench=. -cpuprofile=cpu.prof pkg: github.com/EDDYCJY/go-pprof-example/data BenchmarkAdd-4 10000000 187 ns/op PASS ok github.com/EDDYCJY/go-pprof-example/data 2.300s
-memprofile 也能夠了解一下
$ go tool pprof -http=:8080 cpu.prof
$ go tool pprof cpu.prof $ (pprof) web
若是出現 Could not execute dot; may need to install graphviz.
,就是提示你要安裝 graphviz
了 (請右拐谷歌)
(1)Top
(2)Graph
框越大,線越粗表明它佔用的時間越大哦
(3)Peek
(4)Source
經過 PProf 的可視化界面,咱們可以更方便、更直觀的看到 Go 應用程序的調用鏈、使用狀況等,而且在 View 菜單欄中,還支持如上多種方式的切換
你想一想,在煩惱不知道什麼問題的時候,能用這些輔助工具來檢測問題,是否是瞬間效率翻倍了呢 👌
另外一種可視化數據的方法是火焰圖,需手動安裝原生 PProf 工具:
(1) 安裝 PProf
$ go get -u github.com/google/pprof
(2) 啓動 PProf 可視化界面:
$ pprof -http=:8080 cpu.prof
(3) 查看 PProf 可視化界面
打開 PProf 的可視化界面時,你會明顯發現比官方工具鏈的 PProf 精緻一些,而且多了 Flame Graph(火焰圖)
它就是本次的目標之一,它的最大優勢是動態的。調用順序由上到下(A -> B -> C -> D),每一塊表明一個函數,越大表明佔用 CPU 的時間更長。同時它也支持點擊塊深刻進行分析!
在本章節,粗略地介紹了 Go 的性能利器 PProf。在特定的場景中,PProf 給定位、剖析問題帶了極大的幫助
但願本文對你有所幫助,另外建議可以本身實際操做一遍,最好是能夠深刻琢磨一下,內含大量的用法、知識點 🤓
你很優秀的看到了最後,那麼有兩道簡單的思考題,但願拓展你的思路
(1)flat 必定大於 cum 嗎,爲何?什麼場景下 cum 會比 flat 大?
(2)本章節的 demo 代碼,有什麼性能問題?怎麼解決它?
來,曬出你的想法!😆