go 调优之火焰图
火焰图(flame graphs)是一种程序函数调用栈深度和耗时比例直观可交互展示的工具。
一图胜千言
如上图展示,火焰图展示程序中被频繁调用的函数和耗时占比。这边展示的是一章截图,原图是svg是可交互的,比如我们想具体看某个函数中子函数的情况你可以点击那个函数。结果如下
在go生态中,早期我们经常会用go-torch来生成这样的图。从go1.11后 go tool pprof 就已经集成了这个功能,非常方便我们使用。
演示代码
package main
import (
"encoding/json"
"fmt"
"net/http"
_ "net/http/pprof"
"time"
)
func fn1() {
b := fn2()
fmt.Println(fn3(b))
}
func fn2() (b []byte) {
b, _ = json.Marshal(map[string]int{
"a": 22,
"bb": 333,
})
return
}
func fn3(b []byte) int {
var m map[string]int
json.Unmarshal(b, &m)
if len(m) > 0 {
return m["a"]
}
return 0
}
func main() {
go func() {
for {
fn1()
time.Sleep(1e8)
}
}()
panic(http.ListenAndServe(":8080", nil))
}
如上面代码所示,需要在代码中引入_ "net/http/pprof"
然后需要起一个http服务 http.ListenAndServe(":8080", nil)
,就这样比较少的代码侵入。
运行
$ go run main.go
然后你可以在浏览器中访问,http://127.0.01:8080/debug/pprof/
看到如下的信息
/debug/pprof/
Types of profiles available:
Count Profile
1 allocs
0 block
0 cmdline
5 goroutine
1 heap
0 mutex
0 profile
7 threadcreate
0 trace
...
ok 测试程序没问题了
生成火焰图
step 1
运行如下的命令,下载profile文件
go tool pprof http://127.0.0.1:8080/debug/pprof/profile -seconds 5
step 2
运行如下命令生成火焰图
go tool pprof -http=:8081 ~/pprof/pprof.main.samples.cpu.001.pb.gz
注意:这个时候可能会提升缺少 graphviz ubuntu和debian 使用 apt-get install graphviz 安装
用浏览器访问 http://localhost:8081/ui/flamegraph
这个时候就能看到火焰图了。
调优过程
我们生成火焰图的目录是为了直观的发现程序中最耗时的函数,然后想办法去优化它, 优化后继续生成火焰图看是否有效果,然后再去发现下一个最耗时的函数,重复上面的步骤直到整个程序达到你满意的性能。