程式語言:Go
- Package:
- runtime/pprof
- net/http/pprof
官方文件:Profiling Go Programs
官方文件:net/http/pprof
官方文件:runtime/pprof
官方文件:runtime
官方文件:runtime/debug
功能:檢查性能瓶頸
主要檢測功能
- CPU Profiling
- CPU 分析,按照一定的頻率採集所監聽的應用程序 CPU(含寄存器)的使用情況
可確定應用程序在主動消耗 CPU 週期時花費時間的位置
- Memory Profiling
- Heap 分析,包含每个 goroutine 分配大小,分配堆栈等
- Block Profiling
- 阻塞分析,記錄 goroutine 阻塞等待同步(包括定時器通道)的位置
- Mutex Profiling
go test
- 透過 "go test -bench ." 生成相關訊息
go test -bench . -cpuprofile cpu.prof -memprofile mem.prof -blockprofile block.prof -mutexprofile mutex.prof
- 查詢指令用法
go test -h
- 使用內建 go tool 觀看數據
go tool pprof FileName
top # 顯示前幾名
web # 用瀏覽器觀看圖,需安裝 Graphviz
- 安裝原生 PProf 工具觀看數據,具有 Flame Graph
go get -u github.com/google/pprof # 安裝方法
pprof -http=:8080 FileName
runtime/pprof
net/http/pprof
- 透過 http 服務得到 Profile 採樣文檔,可使用在 server 上
- 查看數據
URI/debug/pprof/
- 使用內建 go tool 觀看數據
go tool pprof URI/debug/pprof/heap
go tool pprof URI/debug/pprof/profile?seconds=30
- 安裝原生 PProf 工具觀看數據,具有 Flame Graph
go get -u github.com/google/pprof # 安裝方法
pprof -http=:8080 URI/debug/pprof/heap
pprof -http=:8080 URI/debug/pprof/profile?seconds=1
測試程式
main.go
- package main
-
- import (
- "log"
- "net/http"
- "os"
- "runtime"
- "runtime/pprof"
- "sync"
- "time"
- )
-
- var mutex sync.Mutex
-
- func main() {
- // 需設定,不然 block profile 不會有值
- runtime.SetBlockProfileRate(1)
- // 需設定,不然 mutex profile 不會有值
- runtime.SetMutexProfileFraction(1)
-
- startPProfCPU()
- fabonacci(10000000)
- stopPProfCPU()
-
- mutex.Lock()
- go test()
- time.Sleep(2 * time.Millisecond)
- mutex.Unlock()
-
- pprofBlock()
- pprofMutex()
- pprofMem()
-
- log.Println(http.ListenAndServe("localhost:6060", nil))
- }
-
- func fabonacci(index int) int {
- if index <= 0 {
- log.Fatal("index is less than 1")
- }
-
- pre0 := 0
- pre1 := 1
- for i := 1; i < index; i++ {
- pre1, pre0 = pre0+pre1, pre1
- }
- return pre1
- }
-
- func test() {
- go func() {
- m := make(map[int]int)
- for i := 0; i < 1000000; i++ {
- m[i] = i
- }
- }()
- mutex.Lock()
- time.Sleep(1 * time.Second)
- mutex.Unlock()
- }
-
- func startPProfCPU() {
- cpuprofile := "cpu.out"
- f, err := os.Create(cpuprofile)
- if err != nil {
- log.Fatal("could not create CPU profile: ", err)
- }
- if err := pprof.StartCPUProfile(f); err != nil {
- log.Fatal("could not start CPU profile: ", err)
- }
- }
-
- func stopPProfCPU() {
- pprof.StopCPUProfile()
- }
-
- func pprofMem() {
- memprofile := "mem.out"
- f, err := os.Create(memprofile)
- if err != nil {
- log.Fatal("could not create memory profile: ", err)
- }
- defer f.Close()
-
- runtime.GC() // get up-to-date statistics
- if err := pprof.WriteHeapProfile(f); err != nil {
- log.Fatal("could not write memory profile: ", err)
- }
- }
-
- func pprofBlock() {
- blockprofile := "block.out"
- f, err := os.Create(blockprofile)
-
- if err != nil {
- log.Fatal("could not create block profile: ", err)
- }
- defer f.Close()
-
- p := pprof.Lookup("block")
- err = p.WriteTo(f, 0)
- if err != nil {
- log.Fatal("could not write write profile: ", err)
- }
- }
-
- func pprofMutex() {
- mutexprofile := "mutex.out"
- f, err := os.Create(mutexprofile)
-
- if err != nil {
- log.Fatal("could not create block profile: ", err)
- }
- defer f.Close()
-
- p := pprof.Lookup("mutex")
- err = p.WriteTo(f, 0)
- if err != nil {
- log.Fatal("could not write write profile: ", err)
- }
- }
main_test.go
- package main
-
- import (
- "testing"
- "time"
- )
-
- func BenchmarkFabonacci(b *testing.B) {
- for i := 0; i < b.N; i++ {
- fabonacci(10)
-
- mutex.Lock()
- go test()
- time.Sleep(2 * time.Millisecond)
- mutex.Unlock()
- }
- }
main_http.go
不能與 main.go 同個資料夾
- package main
-
- import (
- "log"
- "net/http"
- _ "net/http/pprof"
- "sync"
- )
-
- var mutex sync.Mutex
-
- func main() {
- // 重覆運行,以便讓 http/pprof 抓取資料
- go func() {
- for {
- fabonacci(10000000)
- }
- }()
-
- log.Fatal(http.ListenAndServe("localhost:6060", nil))
- }
-
- func fabonacci(index int) int {
- if index <= 0 {
- log.Fatal("index is less than 1")
- }
-
- pre0 := 0
- pre1 := 1
- for i := 1; i < index; i++ {
- pre1, pre0 = pre0+pre1, pre1
- }
- return pre1
- }
其他有用工具
- race 檢測
go run -race main.go
- 用 panic 取代 return 觀察是否還有未關閉的 goroutine
參考
go pprof 性能分析
Golang 大杀器之性能剖析 PProf
golang 使用pprof和go-torch做性能分析
Go 语言运行时环境变量快速导览
留言
張貼留言