性能分析工具pprof
希望知道应用在什么地方耗费了多少CPU、Memory
pprof是用于可视化和分析性能分析数据的工具
pprof一功能简介
pprof一排查实战
搭建pprof 实践项目
项目提前埋入了一些炸弹代码,产生可观测的性能问题
前置准备
.下载项目代码,能够编译运行
·会占用1CPU核心和超过1GB的内存
// main.go
package main
import (
"log"
"net/http"
_ "net/http/pprof" // 自动注册pprof的handler到http server
"os"
"runtime"
"time"
"github.com/wolfogre/go-pprof-practice/animal"
)
func main() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
log.SetOutput(os.Stdout)
runtime.GOMAXPROCS(1) //限制CPU使用数
runtime.SetMutexProfileFraction(1) //开启锁调用跟踪
runtime.SetBlockProfileRate(1) //开启阻塞调用跟踪
go func() {
if err := http.ListenAndServe(":6060", nil); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
for {
for _, v := range animal.AllAnimals {
v.Live()
}
time.Sleep(time.Second)
}
}
网页中有一些指标和选项
CPU
可以在终端输入采样命令,此处采样10s
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
运行完成后,终端输入top命令,可以查看详细信息
flat:当前函数本身的执行耗时
flat%:flat占CPU总时间的比例
sum%:上面每一行的flat%总和
cum:指当前函数本身加上其调用函数的总耗时
cum%:cum占CPU总时间的比例
Flat == Cum,丽数中没有调用其他函数
Flat == 0,函数中只有其他函数的调用
可以根据占比和时间长度找到限制程序效率的关键函数
终端输入list 【函数名】
可以查看具体函数中占用时间最长的代码,如下图,定位到for循环中的一步
使用web命令,可以自动打开网页有可视化调用关系和占比
Heap——堆内存
使用可视化命令
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
打开后可以看到有VIEW选项
具体选项和刚刚在终端使用 的命令类似,比如top
点开网页上的SAMPLE,可以看到四个选项
alloc_objects:程序累计申请的对象数
inuse objects:程序当前持有的对象数
alloc_space:程序累计申请的内存大小
inuse space:程序当前占用的内存大小
打开alloc_space,可以看到,有代码申请了大量额外的内存,这也可以对代码效率造成影响,而通过刚刚的排查,很可能会忽略掉
goroutine协程
使用时可以仿照刚刚的命令,只需要修改最后一个后缀即可
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
打开后发现调用图非常长,不易分析
这次尝试使用flame graph火焰图去分析
从上到下表示调用顺序,每一块代表一个函数,块越长代表CPU占用时间越长,并且火焰图是动态的,可以点击对应函数块进行分析
mutex锁
命令类似前几步:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
查看的步骤也和刚刚类似,看哪种视图方便就用哪种
block阻塞
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
操作类似
打开后发现先前最开始可以看到有2个阻塞,但是只显示了一个
原因就是,pprof会自动过滤一些时间极短的,防止展示内容过多影响分析,如果想看可以去首页点击对应的block链接查看