go性能分析工具pprof的用途及使用詳解
pprof的用途
- CPU Profiling:CPU 分析,按照一定的頻率采集所監(jiān)聽的應用程序 CPU(含寄存器)的使用情況,可確定應用程序在主動消耗CPU 周期時花費時間的位置
- Memory Profiling:內(nèi)存分析,在應用程序進行堆分配時記錄堆棧跟蹤,用于監(jiān)視當前和歷史內(nèi)存使用情況,以及檢查內(nèi)存泄漏
- Block Profiling:阻塞分析,記錄 goroutine 阻塞等待同步(包括定時器通道)的位置。阻塞分析對分析程序并發(fā)瓶頸非常有幫助。
- Mutex Profiling:互斥鎖分析,報告互斥鎖的競爭情況
所以當內(nèi)存或者cpu飆升的時候,我們可以使用go自帶的性能分析利器pprof來查找問題所在。
Go 語言自帶的 pprof 庫就可以分析程序的運行情況,并且提供可視化的功能。它包含兩個相關(guān)的庫:
runtime/pprof
對于只跑一次的程序,例如每天只跑一次的離線預處理程序,調(diào)用 pprof 包提供的函數(shù),手動開啟性能數(shù)據(jù)采集。
net/http/pprof
對于在線服務,對于一個 HTTP Server,訪問 pprof 提供的 HTTP 接口,獲得性能數(shù)據(jù)。當然,實際上這里底層也是調(diào)用的 runtime/pprof 提供的函數(shù),封裝成接口對外提供網(wǎng)絡訪問。
利用runtime/pprof包實現(xiàn)cpu分析的步驟
package main import ( "flag" "fmt" "log" "os" "runtime/pprof" ) //執(zhí)行 go run main -help 查看幫助信息 //執(zhí)行 go run main -cpuprofile cpu.prof 生成cpu性能分析文件 func main() { var cpuprofile = flag.String("cpuprofile", "", "請輸入 -cpuprofile 指定cpu性能分析文件名稱") //在所有flag都注冊之后,調(diào)用:flag.Parse() flag.Parse() f, err := os.Create(*cpuprofile) if err != nil { log.Fatal("could not create CPU profile: ", err) } // StartCPUProfile為當前進程開啟CPU profile。 if err := pprof.StartCPUProfile(f); err != nil { log.Fatal("could not start CPU profile: ", err) } // StopCPUProfile會停止當前的CPU profile(如果有) defer pprof.StopCPUProfile() sum := 0 for i := 0; i < 100; i++ { sum += i } fmt.Printf("sum=%d\n", sum) }
這里對flag.String參數(shù)的解釋如下:
2、執(zhí)行命令生成本地文件cpu.prof:
go run main.go -cpuprofile cpu.prof
3、對文件進行分析:
go tool pprof cpu.prof
對應的參數(shù)說明:
利用runtime/pprof包實現(xiàn)內(nèi)存分析的步驟:
package main import ( "flag" "fmt" "log" "os" "runtime" "runtime/pprof" ) //執(zhí)行 go run main -help 查看幫助信息 //執(zhí)行 go run main -menprofile men.prof 生成內(nèi)存性能分析文件 func main() { var menprofile = flag.String("menprofile", "", "請輸入 -menprofile 指定內(nèi)存性能分析文件名稱") //在所有flag都注冊之后,調(diào)用:flag.Parse() flag.Parse() f, err := os.Create(*menprofile) if err != nil { log.Fatal("could not create memory profile: ", err) } defer f.Close() // error handling omitted for example runtime.GC() // get up-to-date statistics if err := pprof.WriteHeapProfile(f); err != nil { log.Fatal("could not write memory profile: ", err) } sum := 0 for i := 0; i < 100; i++ { sum += i } fmt.Printf("sum=%d\n", sum) }
然后就是生成本地性能分析文件和查看文件:
總結(jié):
其實,我們可以把上面兩個代碼合并,輸入 go run main.go -cpuprofile cpu.prof -menprofile men.prof同時生成cpu和內(nèi)存的性能分析文件。
利用net/http/pprof包進行性能分析
這個很簡單,直接啟動一個端口(和正常提供業(yè)務服務的端口不同)監(jiān)聽 pprof 請求:
package main import ( "fmt" "gin_pro/pkg/setting" "gin_pro/routers" "net/http" _ "net/http/pprof" ) func main() { //用于pprof檢測內(nèi)存使用情況 go func() { http.ListenAndServe("0.0.0.0:8080", nil) }() router := routers.InitRouter() s := &http.Server{ Addr: fmt.Sprintf(":%d", setting.HTTPPort), Handler: router, ReadTimeout: setting.ReadTimeout, WriteTimeout: setting.WriteTimeout, MaxHeaderBytes: 1 << 20, // 1* 2^20 = 1*1024*1024 = 1M } s.ListenAndServe() }
然后在終端執(zhí)行以下命令就能查看對應的數(shù)據(jù)了:
#所有過去內(nèi)存分配的采樣 go tool pprof http://127.0.0.1:8080/debug/pprof/allocs #對活動對象的內(nèi)存分配進行采樣(活動) go tool pprof http://127.0.0.1:8080/debug/pprof/heap # 下載 cpu profile,默認從當前開始收集 30s 的 cpu 使用情況,需要等待 30s go tool pprof http://127.0.0.1:8080/debug/pprof/profile # wait 120s go tool pprof http://127.0.0.1:8080/debug/pprof/profile?seconds=120 #導致同步原語阻塞的堆棧跟蹤 go tool pprof http://127.0.0.1:8080/debug/pprof/block #所有當前goroutine的堆棧跟蹤 go tool pprof http://127.0.0.1:8080/debug/pprof/goroutine #爭用互斥鎖持有者的堆棧跟蹤 go tool pprof http://127.0.0.1:8080/debug/pprof/mutex #當前程序的執(zhí)行軌跡。 go tool pprof http://127.0.0.1:8080/debug/pprof/trace
在可以直接在瀏覽器查看:
http://127.0.0.1:8080/debug/pprof/
總結(jié)
到此這篇關(guān)于go性能分析工具pprof的用途及使用的文章就介紹到這了,更多相關(guān)go性能分析工具pprof內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang多線程下載器實現(xiàn)高效快速地下載大文件
Golang多線程下載器是一種高效、快速地下載大文件的方法。Golang語言天生支持并發(fā)和多線程,可以輕松實現(xiàn)多線程下載器的開發(fā)。通過使用Golang的協(xié)程和通道,可以將下載任務分配到多個線程中并行處理,提高了下載的效率和速度2023-05-05