應用程序在運行時,總是會出現一些你意想不到的問題,例如:CPU使用率過高,內存不斷增大(疑似內存泄露),或者是Goroutine數量不斷增加(goroutine泄露)。那么在這些問題出現時如何進行排查呢,這里介紹pprof工具。
pprof是什么
pprof是析性能分析數據的工具,可以生成可視化的文本和圖形報告幫助分析程序問題和數據。
基本使用
package main
import (
"net/http"
_ "net/http/pprof" // 會自動注冊 handler 到 http server,方便通過 http 接口獲取程序運行采樣報告
"runtime"
"time"
)
func main() {
runtime.SetMutexProfileFraction(1) // 開啟對鎖調用的跟蹤
runtime.SetBlockProfileRate(1) // 開啟對阻塞操作的跟蹤
go Loop()
_ = http.ListenAndServe(":9000", nil)
}
func Loop() {
for i := 0; i < 10000000000; i++ {
time.Sleep(time.Microsecond*100)
}
}
這里要在import中添加_ "net/http/pprof"來獲取采樣報告,然后運行程序,訪問http://127.0.0.1:9000/debug/pprof/查看報告。
通過web報告分析
allocs:查看過去所有內存分配的樣本。
block:查看導致阻塞同步的堆棧跟蹤。
cmdline: 當前程序的命令行的完整調用路徑。
goroutine:查看當前所有運行的 goroutines 堆棧跟蹤。
heap:查看活動對象(堆)的內存分配情況。
mutex:查看導致互斥鎖的競爭持有者的堆棧跟蹤。
profile: 默認進行 30s 的 CPU Profiling,得到一個分析用的 profile 文件。
threadcreate:查看創建新 OS 線程的堆棧跟蹤。
點擊頁面的某一項還可以看到更詳細的信息
通過互交式終端分析
直接通過命令行,來完成對正在運行的應用程序 pprof 的抓取和分析。
package main
import (
"net/http"
_ "net/http/pprof" // 會自動注冊 handler 到 http server,方便通過 http 接口獲取程序運行采樣報告
"runtime"
"time"
)
func main() {
runtime.SetMutexProfileFraction(1) // 開啟對鎖調用的跟蹤
runtime.SetBlockProfileRate(1) // 開啟對阻塞操作的跟蹤
go G()
// 這里可以指定監聽ip,例如:_ = http.ListenAndServe("127.0.0.1:9000", nil)
_ = http.ListenAndServe(":9000", nil)
}
func G() {
for i := 0; i < 10000; i++ {
go func() {
s := make([]int,1000)
for i := 0; i < 10000; i++ {
s = append(s,i)
time.Sleep(time.Millisecond*500)
}
}()
time.Sleep(time.Millisecond*5)
}
}
再起一個命令行輸入命令:
go tool pprof http://127.0.0.1:9000/debug/pprof/heap?seconds=60
這里的heap可以換成上面的goroutine,profile等任意一個,參數seconds如果不填默認30s。
然后就可以得到互交界面:
上面Saved profile... 這里保持了文件。
Type: inuse_space 分析應用程序的常駐內存占用情況。
這里還可以用命令:o tool pprof -alloc_objects http://127.0.0.1:9000/debug/pprof/heap
(alloc_objects:分析應用程序的內存臨時分配情況; inuse_objects:每個函數所分別的對象數量; alloc_space:查看分配的內存空間大小)。
top命令
查看內存使用情況,從高到低排序:
- flat:函數自身的運行耗時。
- flat%:函數自身在 CPU 運行耗時總比例。
- sum%:函數自身累積使用 CPU 總比例。
- cum:函數自身及其調用函數的運行總耗時。
- cum%:函數自身及其調用函數的運行耗時總比例。
- 最后一個是函數名。
list+函數名 命令
可以具體的看到函數在哪一行消耗的內存。
traces 命令
這個命令會打印出對應的所有調用棧,以及指標信息,可以讓我們很便捷的查看到整個調用鏈路有什么,分別在哪里使用了多少個內存。
通過可視化界面分析
直接輸入命令:web
提示我們沒有安裝Graphviz,先去Graphviz官網下載安裝,這里可以直接勾選安裝環境變量。
然后再輸入web可以看到函數調用的流程圖,改圖全面整體的展示了函數的調用情況,用線的粗細,顏色表明開銷的大小程度,很形象。
如果需要分析goroutine,profile等,和上面的流程一樣。pprof對程序的性能優化還是很有利的,它可以快速定位到耗時較多的位置進行優化,而且也支持只打印和某個函數相關的命令,很人性化。