本文会详细讲述如何通过pprof分析go程序的性能,让你看懂自己的程序都是在哪消耗的性能。本文从下面四个方面去讲述:
1、 如何在程序中开启pprof:web服务和非web服务
2、 通过pprof分析CPU使用以及如何看懂他们的输出:分析各个函数执行时间的长度,让你知道代码是怎么写挫的
3、 通过pprof分析内存的分配:看看你的代码哪里申请的内存不合理,如何优化
4、 讲述一些pprof的边缘使用:主要是指引一下,后续留给你去探索
本文就不对pprof的命令(本文就用了top${n},web, list)进行详细讲解,因为通过help命令看一下就知道了,就那么几个。
注:文中的代码在
https://github.com/helios741/benchgraffiti/tree/master/havlak
如果是非web程序开启pprof的话使得用的runtime/pprof包,开启方式如下:
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
func main() {
flag.Parse()
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
defer f.Close()
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
if *memprofile != "" {
f, err := os.Create(*memprofile)
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
defer f.Close()
pprof.WriteHeapProfile(f)
}
...
}
比如你的代码通过go build产生出的二进制叫做main,那么./main -cpuprofile=cpu.prof -memprofile=mem.prof 产出pprof能分析的文件即可。
如果是web程序的话,使用的是net/http/pprof包,比较简单,只需下面代码即可:
import _ "net/http/pprof"
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
go tool pprof http://localhost:6060/debug/pprof/heap
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
图一,CPU使用的top10
图二,CPU累计的前十名
图三,pprof svc展示图
我们能只看一个分支,比如说只想看DFS函数,可以执行
(pprof) web DFS
图四、DFS函数svg图
看到mapaccess应该就看懂,肯定是DFS函数中使用骚操作的map。我们通过下面的命令看一下DFS的代码:
(pprof) list DFS
图五、DFS代码
输出的前三列分别表示该行代码运行的时长、该行代码加上以前运行的时间、以及代码行数。
241, 242, 246, and 250这四行使用了map。map的key是对象引用起来会变得特别慢。我们改为map[int]int再来看一下。
我们这里以非web方式来做个例子(go tool pprof mem.prof)。
看一下内存消耗资源的前五名:
图七、memory耗时前五名
明显看到FindLoops是个大头,看一下代码:
图八、FindLoops代码
我们知道golang对于大内存会分配在堆上,堆有两个坏处,一个是慢二是会被GC。所以这肯定不好。
图九、FindLoops大量申请内存部分代码
将这段代码进行优化(改为slice)后:
降低了很多。
本来以为优化了上面之后gc时间也会大大减少呢,结果并没有那么明显,从23.27% -> 23.05%。也可能是我的go版本过于新(1.14)了,在gc上的优化已经够好了,以后遇到gc时间过长(40%以上)也可以这么分析。
本文主要分析了内存的cpu,其实还有很多的内容可以分析。比如分析你如果在程序中调用runtime.SetBlockProfileRate可以观察goroutine的性能。具体的可以参考https://pkg.go.dev/net/http/pprof。
对于调试web服务还是有很多优势的,比如你要远程看你线上服务的性能,的可以这样(其他指标类似):
go tool pprof -http=:6060 http://172.26.186.76:6060/debug/pprof/profile
过一会在你本地就会自动打开浏览器,就会显示下面的图:
我们一般会看火焰图,点击左上角的VIEW就能看到,
随着一张炫酷的图,这篇文章也结束了。
参考:
https://blog.golang.org/pprof
欢迎长按下面的二维码关注云影原生生公众号