net/http/pprof
runtime/pprofimport _ "net/http/pprof"http.DefaultServeMux
package pprof
func init() {
http.HandleFunc("/debug/pprof/", Index)
http.HandleFunc("/debug/pprof/cmdline", Cmdline)
http.HandleFunc("/debug/pprof/profile", Profile)
http.HandleFunc("/debug/pprof/symbol", Symbol)
http.HandleFunc("/debug/pprof/trace", Trace)
}
github.com/DeanThompson/ginpprofginpprof.Wrap(router)
package main
import (
"github.com/gin-gonic/gin"
"github.com/DeanThompson/ginpprof"
)
func main() {
router := gin.Default()
// automatically add routers for net/http/pprof
// e.g. /debug/pprof, /debug/pprof/heap, etc.
ginpprof.Wrap(router)
// ginpprof also plays well with *gin.RouterGroup
// group := router.Group("/debug/pprof")
// ginpprof.WrapGroup(group)
}
benchmark pprof
go test -bench -run none -cpuprofile -cpuprofile-benchmem -memprofile-blockprofile
runtime/pprof
cpu.profmem.prof
import "runtime/pprof"
func main() {
f, _ := os.Create("cpu.prof")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
ff, _ := os.Create("mem.prof")
pprof.WriteHeapProfile(ff)
// 待测试的程序
}
采样频率
报告查看protobufruntime.SetBlockProfileRate(1)runtime.SetMutexProfileFraction(1)
命令行模式
pprof [options] [binary] go tool pprof http:///debug/pprof/[?seconds=120]secondsgo tool pprof toptraceslist top -cumtraces - - - - -list
浏览器模式
pprof -http [host]:[port] [options] [binary] wgetcurlscpTopGraphFlame Graphgraphvizbrew install graphvizapt install graphvizSource
--nodecount=<n> Show at most so many nodes [default=80]
--nodefraction=<f> Hide nodes below <f>*total [default=.005]
--edgefraction=<f> Hide edges below <f>*total [default=.001]
Flame Graph
使用源代码
listsourceError: could not find file xx on path xxx-source_path-trim_path$GOPATH/personal/demo_old$GOPATH/personal/demo_newgo tool pprof -source_path=$GOPATH/personal/demo_new -trim_path=$GOPATH/personal/demo_old /ln -sln -s $GOPATH /opt/xxx/compile_path
指标分析
CPU
- CPU 性能分析启用后,Go runtime 会每 10ms 就暂停一下,记录当前运行的 goroutine 的调用堆栈及相关数据
- 出现频率较高的函数则CPU占用较高
- 该指标记录的耗时是主动消耗CPU的时间(on-cpu),不包括I/O等待和sleeping等时间(off-cpu)
- 对于IO消耗型的任务,on-cpu并不能代表任务大部分的时间消耗在了哪里
off-cpu
- off-cpu包括:
- 进程进入系统调用执行(磁盘、网络)io动作的时间
- 进程等待mutex锁的时间
- 内存被交换,swap的时间
- 内存不够的时候,执行直接内存回收的时间
- 进程被抢占调度走、或者时间片用完被调度走的时间
耗时分析
runtime.GoruntineProfile
内存
inuseallocgo tool pprof-sample_indexgo tool pprof -sample_index=alloc_space http:///debug/pprof/heapgo tool pprof -base toplistmProf_MallocmProf_Freeinused_spacerssdebug/pprof/heap?debug=1runtime.MemStats
goroutine
go tool pprof -base
goroutine?debug=1
- 查看某条调用路径上,当前阻塞在此goroutine的数量
- 不会列出单独的 goroutines 信息,把拥有相同堆栈信息和标签的 goroutines 和他们的数量一起列出
goroutine profile: total 32023
32015 @ 0x42e15a 0x42e20e 0x40534b 0x4050e5 0x6d8559 0x6d831b 0x45abe1
# 0x6d8558 main.alloc2.func1+0xf8 /home/ubuntu/heap/leak_demo.go:53
# 0x6d831a main.alloc2+0x2a /home/ubuntu/heap/leak_demo.go:54
goroutine profile: total 3202332015 @ 0x42e15a 0x42e20e 0x40534b 0x4050e5 ...# 0x6d8558 main.alloc2.func1+0xf8 /home/ubuntu/heap/leak_demo.go:53
goroutine?debug=2
- 查看所有goroutine的运行栈(调用路径)
- 可以显示该gorotine当前在干什么以及阻塞在此的时间
- 以分钟为单位包含在内,但前提是持续时间超过 1 分钟
- 最上方显示的是当前运行的goroutine
goroutine 20 [chan send, 2 minutes]:
main.alloc2.func1(0xc42015e060)
/home/ubuntu/heap/leak_demo.go:53 +0xf9
main.alloc2(0xc42015e060)
/home/ubuntu/heap/leak_demo.go:54 +0x2b
created by main.alloc1
/home/ubuntu/heap/leak_demo.go:42 +0x3f
goroutine 20 [chan send, 2 minutes]20[]
- 参考:
阻塞(mutex & block)
-
block分析用法
-
block并不能分析大部分的耗时之处,主要用于分析锁和channel(即并发相关)的操作消耗
-
mutex和block指标的关系
-
借助CPU分支预测技术,block在不开启时几乎没有消耗