go性能分析工具pprof的用途及使用詳解
pprof的用途
- CPU Profiling:CPU 分析,按照一定的頻率采集所監(jiān)聽(tīng)的應(yīng)用程序 CPU(含寄存器)的使用情況,可確定應(yīng)用程序在主動(dòng)消耗CPU 周期時(shí)花費(fèi)時(shí)間的位置
- Memory Profiling:內(nèi)存分析,在應(yīng)用程序進(jìn)行堆分配時(shí)記錄堆棧跟蹤,用于監(jiān)視當(dāng)前和歷史內(nèi)存使用情況,以及檢查內(nèi)存泄漏
- Block Profiling:阻塞分析,記錄 goroutine 阻塞等待同步(包括定時(shí)器通道)的位置。阻塞分析對(duì)分析程序并發(fā)瓶頸非常有幫助。
- Mutex Profiling:互斥鎖分析,報(bào)告互斥鎖的競(jìng)爭(zhēng)情況
所以當(dāng)內(nèi)存或者cpu飆升的時(shí)候,我們可以使用go自帶的性能分析利器pprof來(lái)查找問(wèn)題所在。
Go 語(yǔ)言自帶的 pprof 庫(kù)就可以分析程序的運(yùn)行情況,并且提供可視化的功能。它包含兩個(gè)相關(guān)的庫(kù):
runtime/pprof
對(duì)于只跑一次的程序,例如每天只跑一次的離線預(yù)處理程序,調(diào)用 pprof 包提供的函數(shù),手動(dòng)開(kāi)啟性能數(shù)據(jù)采集。
net/http/pprof
對(duì)于在線服務(wù),對(duì)于一個(gè) HTTP Server,訪問(wèn) pprof 提供的 HTTP 接口,獲得性能數(shù)據(jù)。當(dāng)然,實(shí)際上這里底層也是調(diào)用的 runtime/pprof 提供的函數(shù),封裝成接口對(duì)外提供網(wǎng)絡(luò)訪問(wèn)。
利用runtime/pprof包實(shí)現(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", "", "請(qǐng)輸入 -cpuprofile 指定cpu性能分析文件名稱")
//在所有flag都注冊(cè)之后,調(diào)用:flag.Parse()
flag.Parse()
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
// StartCPUProfile為當(dāng)前進(jìn)程開(kāi)啟CPU profile。
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
// StopCPUProfile會(huì)停止當(dāng)前的CPU profile(如果有)
defer pprof.StopCPUProfile()
sum := 0
for i := 0; i < 100; i++ {
sum += i
}
fmt.Printf("sum=%d\n", sum)
}這里對(duì)flag.String參數(shù)的解釋如下:


2、執(zhí)行命令生成本地文件cpu.prof:
go run main.go -cpuprofile cpu.prof

3、對(duì)文件進(jìn)行分析:
go tool pprof cpu.prof

對(duì)應(yīng)的參數(shù)說(shuō)明:

利用runtime/pprof包實(shí)現(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", "", "請(qǐng)輸入 -menprofile 指定內(nèi)存性能分析文件名稱")
//在所有flag都注冊(cè)之后,調(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é):
其實(shí),我們可以把上面兩個(gè)代碼合并,輸入 go run main.go -cpuprofile cpu.prof -menprofile men.prof同時(shí)生成cpu和內(nèi)存的性能分析文件。
利用net/http/pprof包進(jìn)行性能分析
這個(gè)很簡(jiǎn)單,直接啟動(dòng)一個(gè)端口(和正常提供業(yè)務(wù)服務(wù)的端口不同)監(jiān)聽(tīng) pprof 請(qǐng)求:
package main
import (
"fmt"
"gin_pro/pkg/setting"
"gin_pro/routers"
"net/http"
_ "net/http/pprof"
)
func main() {
//用于pprof檢測(cè)內(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í)行以下命令就能查看對(duì)應(yīng)的數(shù)據(jù)了:
#所有過(guò)去內(nèi)存分配的采樣 go tool pprof http://127.0.0.1:8080/debug/pprof/allocs #對(duì)活動(dòng)對(duì)象的內(nèi)存分配進(jìn)行采樣(活動(dòng)) go tool pprof http://127.0.0.1:8080/debug/pprof/heap # 下載 cpu profile,默認(rèn)從當(dāng)前開(kāi)始收集 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 #導(dǎo)致同步原語(yǔ)阻塞的堆棧跟蹤 go tool pprof http://127.0.0.1:8080/debug/pprof/block #所有當(dāng)前goroutine的堆棧跟蹤 go tool pprof http://127.0.0.1:8080/debug/pprof/goroutine #爭(zhēng)用互斥鎖持有者的堆棧跟蹤 go tool pprof http://127.0.0.1:8080/debug/pprof/mutex #當(dāng)前程序的執(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go使用Gin+mysql實(shí)現(xiàn)增刪改查的詳細(xì)實(shí)例
golang本身沒(méi)有提供連接mysql的驅(qū)動(dòng),但是定義了標(biāo)準(zhǔn)接口供第三方開(kāi)發(fā)驅(qū)動(dòng),下面這篇文章主要給大家介紹了關(guān)于Go使用Gin+mysql實(shí)現(xiàn)增刪改查的相關(guān)資料,需要的朋友可以參考下2022-12-12
利用go語(yǔ)言實(shí)現(xiàn)Git?重命名遠(yuǎn)程分支??
這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)Git?重命名遠(yuǎn)程分支,文章基于go語(yǔ)言的基礎(chǔ)展開(kāi)Git?重命名遠(yuǎn)程分支的實(shí)現(xiàn)過(guò)程,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助2022-06-06
關(guān)于Golang標(biāo)準(zhǔn)庫(kù)flag的全面講解
這篇文章主要介紹了關(guān)于Golang標(biāo)準(zhǔn)庫(kù)flag的全面講解,這個(gè)庫(kù)的代碼量只有1000行左右,卻提供了非常完善的命令行參數(shù)解析功能,更多相關(guān)內(nèi)容需要的朋友可以參考一下2022-09-09
Go語(yǔ)言實(shí)現(xiàn)聊天小工具的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Go語(yǔ)言實(shí)現(xiàn)聊天小工具,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
Gorm存在時(shí)更新,不存在時(shí)創(chuàng)建的問(wèn)題
這篇文章主要介紹了Gorm存在時(shí)更新,不存在時(shí)創(chuàng)建的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
關(guān)于go-zero服務(wù)自動(dòng)收集問(wèn)題分析
這篇文章主要介紹了關(guān)于go-zero服務(wù)自動(dòng)收集問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
Go語(yǔ)言利用接口實(shí)現(xiàn)鏈表插入功能詳解
這篇文章主要為大家介紹了Go語(yǔ)言中的接口,以及如何利用接口實(shí)現(xiàn)鏈表插入功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-04-04

