这是我参与「第五届青训营」伴学笔记创作活动的第10天
内容梗概
本文主要梳理了以下内容:
- 性能调优概念
- pprof
1 基本概念
2 pprof数据采样
pprof 采样数据主要有三种获取方式:
-
runtime/pprof: 手动调用
runtime.StartCPUProfile或者runtime.StopCPUProfile等 API来生成和写入采样文件,灵活性高 -
net/http/pprof: 通过 http 服务获取Profile采样文件,简单易用,适用于对应用程序的整体监控。通过 runtime/pprof 实现
-
go test: 通过
go test -bench . -cpuprofile prof.cpu生成采样文件 适用对函数进行针对性测试
1.1 net/http/pprof
在应用程序中导入import _ "net/http/pprof",并启动 http server即可:
// net/http/pprof 已经在 init()函数中通过 import 副作用完成默认 Handler 的注册
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
之后可通过 http://localhost:6060/debug/pprof/CMD 获取对应的采样数据。支持的 CMD 有:
- goroutine: 获取程序当前所有 goroutine 的堆栈信息。
- heap: 包含每个 goroutine 分配大小,分配堆栈等。每分配 runtime.MemProfileRate(默认为512K) 个字节进行一次数据采样。
- threadcreate: 获取导致创建 OS 线程的 goroutine 堆栈
- block: 获取导致阻塞的 goroutine 堆栈(如 channel, mutex 等),使用前需要先调用
runtime.SetBlockProfileRate - mutex: 获取导致 mutex 争用的 goroutine 堆栈,使用前需要先调用
runtime.SetMutexProfileFraction
以上五个 CMD 都通过runtime/pprof Profile 结构体统一管理,以 Lookup 提供统一查询接口,有相似的返回值(goroutine 堆栈),它们都支持一个 debug URL参数,默认为0,此时返回的采样数据是不可人为解读的函数地址列表,需要结合 pprof 工具才能还原函数名字。 debug=1时,会将函数地址转换为函数名,即脱离 pprof 在浏览器中直接查看。对 goroutine CMD来说,还支持 debug=2,此时将以 unrecovered panic 的格式打印堆栈,可读性更高。如启用net/http/pprof后,http://localhost:6060/debug/pprof/goroutine?debug=2 的响应格式为:
goroutine 18 [chan receive, 8 minutes]:
ngs/core/glog.logWorker(0x18b548a, 0x4, 0x7fff5fbffb0e, 0x0, 0x3, 0xc4200e31a0, 0xc4203627c4)
/Users/wudaijun/go/src/ngs/core/glog/worker.go:43 +0x19c
created by ngs/core/glog.newLogger
/Users/wudaijun/go/src/ngs/core/glog/glog.go:51 +0xe4
goroutine 6 [syscall, 8 minutes]:
os/signal.signal_recv(0x0)
/usr/local/Cellar/go/1.9.1/libexec/src/runtime/sigqueue.go:131 +0xa7
os/signal.loop()
/usr/local/Cellar/go/1.9.1/libexec/src/os/signal/signal_unix.go:22 +0x22
created by os/signal.init.0
/usr/local/Cellar/go/1.9.1/libexec/src/os/signal/signal_unix.go:28 +0x41
goroutine 50 [select, 8 minutes]:
context.propagateCancel.func1(0x1cfcee0, 0xc42017a1e0, 0x1cf3820, 0xc42005b480)
/usr/local/Cellar/go/1.9.1/libexec/src/context/context.go:260 +0x113
created by context.propagateCancel
/usr/local/Cellar/go/1.9.1/libexec/src/context/context.go:259 +0x1da
...
以上几种 Profile 可在 http://localhost:6060/debug/pprof/ 中看到,除此之外,go pprof 的 CMD 还包括:
- cmdline: 获取程序的命令行启动参数
- profile: 获取指定时间内(从请求时开始)的cpuprof,倒计时结束后自动返回。参数: seconds, 默认值为30。cpuprofile 每秒钟采样100次,收集当前运行的 goroutine 堆栈信息。
- symbol: 用于将地址列表转换为函数名列表,地址通过’+’分隔,如 URL/debug/pprof?0x18d067f+0x17933e7
- trace: 对应用程序进行执行追踪,参数: seconds, 默认值1s
这几个 CMD 因为各种原因没有整合到 Profile 结构中去,但就使用上而言,是没有区别的,URL格式是一致的,因此可以看做一个整体,从各个角度对系统进行数据采样和分析。