前言,发现一直没有记录过 pprof 分析的博客,其实在实际的业务场景中已经使用它很多次了,对于性能分析来说它真的是一大杀器,基本上有了它,80% 的性能问题都能被一目了然。每次出现性能问题,总是下面几个步骤,测试环境开 pprof,启动,流量重放,火焰图生成,一看,仔细分析一下,问题就浮于水面。
今天来用最简单的一个案例,来让你快速上手 pprof,所以本博客包含以下内容
废话不多直接上案例
首先你肯定有 go 环境,需要看火焰图还需要安装 graphviz http://www.graphviz.org/download/
第一个坑来了,如果 mac 使用 brew install graphviz 安装容易出现失败,还有很多奇怪的依赖如 svn java 等,所以建议使用 sudo port install graphviz 安装
使用一些监控软件发现问题,如当前我发现有一个项目在刚启动之后,其他相同类似的项目 cpu 使用都是 20 多,但是它有 40 多(虽然很少了,但是相较于其他先相同服务来说太多了)想知道为什么,所以想来分析一下。
pprof 需要你再代码里面主动声明开启
如果你的项目没有使用任何 web 框架的话,可以使用如下方式开启
import (
_ "net/http/pprof"
)
// 代码中加入
http.ListenAndServe(":8080", nil)
pprof 包中有 init 函数,会主动注册相关路由,只要你监听对应一个端口,则可以使用了
访问 : http://127.0.01:8080/debug/pprof/
因为你的项目使用了 web 框架,所以默认的引入方式没办法注册到你自己创建的路由上,所以需要使用一些特殊手段,这里以 gin 框架举例
import (
"github.com/gin-contrib/pprof"
)
// 代码中加入
r := gin.New()
pprof.Register(r)
其实里面的代码也很简单,就是将 pprof 暴露的 handler 包装了一下,将对应的路由注册上就可以,其他相关的 web 框架也应该都有类似的方案
首先你查看之后会有这样一个页面,上面的一些基本信息你就能看到了,最长使用的就是 goroutine 和 heap 了,能很好的看到每个 goroutine 在干嘛,堆里面有哪些东西等等。
这里没有什么花里胡哨的各种命令,直接说最简单最常使用的火焰图(还有 top 等其他命令可以查看对应文档学习)
go tool pprof http://127.0.0.1:8080/debug/pprof/profile
然后耐心等待 30s 左右会生成对应的 cpu 使用采样文件
Fetching profile over HTTP from http://127.0.0.1:8080/debug/pprof/profile Saved profile in /Users/linkinstar/pprof/pprof.orders.samples.cpu.001.pb.gz
如果相关分析的是内存而不是 cpu 则需要将地址 http://127.0.0.1:8080/debug/pprof/profile 修改为 -> http://127.0.0.1:8080/debug/pprof/heap
会弹出一个命令行交互程序输入 help 可以查看相关命令
新开一个命令行窗口:
go tool pprof -http=:8081 /Users/linkinstar/pprof/pprof.orders.samples.cpu.001.pb.gz
后面的路径为上面生成的采样文件的路径
然后你就能到一个 web 界面了
Ps: 当然你也可以将两个命令合成为一个命令进行使用,如
go tool pprof -http=:8081 127.0.0.1:8080/debug/pprof/heap
首先从 view 中选择 flame graph
然后你就能看到火焰图了,一开始看可能会有点懵,不要紧,告诉你三点,然后就很简单了:
当前我们看到这个生成的火焰图中横轴最长的就是 resolveServiceFromConsul 方法
显然就是这个方法占用了很多 cpu 资源,那么就很清楚了,去代码里面看,这个方法在干什么,原来是 consul 和各个注册微服务的消息交互导致。问题不大。
可以通过 –base 参数对比两个采样数据 tool pprof -http=:9999 --base ./heap.1 heap.2
下面是干货分享,总结了一些最常用的 pprof 的命令如下
# 下载 cpu profile 默认从当前开始收集30s的cρu使用情况, 需要等待3θs
go tool pprof http://127.0.0.1:8080/debug/profile
# wait 120s
go tool pprof http://127.0.0.1:8080/debug/pprof/profile?seconds=120
# 下载 heap profile
go tool pprof http://127.0.0.1:8080/debug/pprof/heap
# 下载特定类型的heap
go tool pprof -sample_index=alloc_space http://127.0.0.1:8080/debug/pprof/heap
go tool pprof --inuse_objects http://127.0.0.1:8080/debug/pprof/heap
# 比较base
go tool pprof -base pprof.demo.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz pprof.demo.alloc_objects.alloc_ space.inuse_objects.inuse_space.002.pb.gz
# 下载 goroutine profile
go tool pprof http://127.0.0.1:8080/debug/pprof/goroutine
# 下载 block profile
go tool pprof http://127.0.0.1:8080/debug/pprof/block
# 下载 mutex profile
go tool pprof http://127.0.0.1:8080/debug/pprof/mutex
# 在浏览器里交互
go tool pprof --http=:8080 ~/Downloads/LinkinStar/profile
pprof 还有很多其他功能,这里是最快的入门方式,让你快速能领略这个工具分析的方法,使用其实非常简单,不过显然实际出现问题没有那么简单,有时候经常会出现 cpu 占用最多的是 runtime 的代码,或者有一些内存泄露的分析需要细细排查原因,如果你没有用起来的话,赶紧上吧!