火焰图(flame graphs)是一种程序函数调用栈深度和耗时比例直观可交互展示的工具。
一图胜千言

如上图展示,火焰图展示程序中被频繁调用的函数和耗时占比。这边展示的是一章截图,原图是svg是可交互的,比如我们想具体看某个函数中子函数的情况你可以点击那个函数。结果如下

在go生态中,早期我们经常会用github.com/uber-archive/go-torch来生成这样的图。从go1.11后 go tool pprof 就已经集成了这个功能,非常方便我们使用。
演示代码
package mainimport ("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]intjson.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://localhost:8080/debug/pprof/
看到如下的信息
/debug/pprof/Types of profiles available:CountProfile1allocs0block0cmdline5goroutine1heap0mutex0profile7threadcreate0trace...
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这个时候就能看到火焰图了。
调优过程
我们生成火焰图的目录是为了直观的发现程序中最耗时的函数,然后想办法去优化它, 优化后继续生成火焰图看是否有效果,然后再去发现下一个最耗时的函数,重复上面的步骤直到整个程序达到你满意的性能。