分析过程
- 第一步,在引用中加上
"net/http"
_ "net/http/pprof"
- 第二步,在代码开始运行的地方加上
go func() {
if err := http.ListenAndServe(":6060", nil); err != nil && err != http.ErrServerClosed {
log.Fatalf("pprof listen: %s\n", err)
}
}()
介绍
allocs:查看过去所有内存分配的样本。
block:查看导致阻塞同步的堆栈跟踪。
cmdline: 当前程序的命令行的完整调用路径。
goroutine:查看当前所有运行的 goroutines 堆栈跟踪。
heap:查看活动对象的内存分配情况。
mutex:查看导致互斥锁的竞争持有者的堆栈跟踪。
profile: 默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件。
threadcreate:查看创建新 OS 线程的堆栈跟踪。
trace:略,trace可以单独写一篇文章来介绍。
1. 分析cpu
go tool pprof http://127.0.0.1:6060/debug/pprof/profile
top 命令 查看数据
保持程序运行,打开浏览器访问 http://localhost:6060/debug/pprof/
- 说明
- flat flat%
flat只会记录step2和step3的时间;flat%即是flat/总运行时间。内存等参数同理。
所有的flat相加即是总采样时间,所有的flat%相加应该等于100%。
flat一般是我们最关注的。其代表一个函数可能非常耗时,或者调用了非常多次,或者两者兼而有之,从而导致这个函数消耗了最多的时间。
如果是我们自己编写的代码,则很可能有一些无脑for循环、复杂的计算、字符串操作、频繁申请内存等等。
如果是第三方库的代码,则很可能我们过于频繁地调用了这些第三方库,或者以不正确的方式使用了这些第三方库。- cum cum%
相比flat,cum则是这个函数内所有操作的物理耗时,比如包括了上述的step1、2、3、4。
cum%即是cum的时间/总运行时间。内存等参数同理。
一般cum是我们次关注的,且需要结合flat来看。flat可以让我们知道哪个函数耗时多,而cum可以帮助我们找到是哪些函数调用了这些耗时的(flat值大的)函数。- sum%
其上所有行的flat%的累加。可以视为,这一行及其以上行,其所有的directly操作一共占了多少物理时间。
2. 内存
go tool pprof http://localhost:6060/debug/pprof/heap
3. 排查频繁内存回收
GODEBUG=gctrace=1 ./main | grep gc
go tool pprof http://localhost:6060/debug/pprof/allocs
同样使用 top、list、web 大法
4. 排查协程泄露
go tool pprof http://localhost:6060/debug/pprof/goroutine
同样使用 top、list、web 大法
5. 排查锁的争用
go tool pprof http://localhost:6060/debug/pprof/mutex
同样使用 top、list、web 大法
6. 排查阻塞操作
go tool pprof http://localhost:6060/debug/pprof/block
同样使用 top、list、web 大法
参考资料
https://blog.wolfogre.com/posts/go-ppof-practice/
https://zhuanlan.zhihu.com/p/396363069