golang 性能调优分析工具 pprof(上)篇, 这是下篇。html
go version go1.13.9git
把上面的程序例子稍微改动下,命名为 demohttp.go:github
package main import ( "bytes" "fmt" "io/ioutil" "log" "math/rand" "net/http" _ "net/http/pprof" "sync" ) func main() { http.HandleFunc("/pprof-test", handler) fmt.Println("http server start") err := http.ListenAndServe(":8090", nil) if err != nil { log.Fatal(err) } } func handler(resp http.ResponseWriter, req *http.Request) { var wg sync.WaitGroup wg.Add(200) for i := 0; i < 200; i++ { go cyclenum(30000, &wg) } wg.Wait() wb := writeBytes() b, err := ioutil.ReadAll(wb) if err != nil { resp.Write([]byte(err.Error())) return } resp.Write(b) } func cyclenum(num int, wg *sync.WaitGroup) { slice := make([]int, 0) for i := 0; i < num; i++ { for j := 0; j < num; j++ { j = i + j slice = append(slice, j) } } wg.Done() } func writeBytes() *bytes.Buffer { var buff bytes.Buffer for i := 0; i < 30000; i++ { buff.Write([]byte{'a' + byte(rand.Intn(10))}) } return &buff }
先运行上面的 demohttp.go 程序,执行命令:golang
go run demohttp.goweb
而后在浏览器输入:http://localhost:8090/debug/pprof/,查看服务运行状况,以下图:浏览器
名称 | url | 说明 |
---|---|---|
allocs | $host/debug/pprof/allocs?debug=1 | 过去全部内存抽样状况 |
block | $host/debug/pprof/block?debug=1 | 同步阻塞时程序栈跟踪的一些状况 |
heap | $host/debug/pprof/heap?debug=1 | 活动对象的内存分配状况 |
mutex | $host/debug/pprof/mutex?debug=1 | 互斥锁持有者的栈帧状况 |
profile | $host/debug/pprof/profile | cpu profile,点击时会获得一个文件,而后能够用 go tool pprof 命令进行分析 |
threadcreate | $host/debug/pprof/threadcreate?debug=1 | 建立新 OS 线程的堆栈跟踪状况 |
trace | $host/debug/pprof/trace | 当前程序执行的追踪状况,点击时会获得一个文件,能够用 go tool trace 命令来分析这个文件 |
点击上面的连接,就能够查看具体的分析状况。
不断刷新网页,能够看到数据在不断变化。app
在命令行上运行 demohttp.go 程序,执行命令:框架
go run demohttp.gosvg
A. 分析 cpu profile函数
在开启另一个命令行终端,执行以下命令:
go tool pprof http://localhost:8090/debug/pprof/profile?seconds=70
参数 seconds = 70:进行 70s 的数据样本采集,这个参数能够根据实际状况调整。
上面的命令执行后,会等待 70s , 而后才会进入命令交互界面,如上图
输入 top
命令:
你们发现没,其实与上面 runtime/pprof 在命令行交互时是同样的操做,能够参考上面的字段参数说明。
找出耗时代码部分,也能够用命令:list
。
在 top
命令执行后,发现什么问题没?这个 top 命令显示的信息都是系统调用信息耗时,没有用户定义的函数。为何?下面进行分析。
B. 分析 memory profile
执行命令:
go tool pprof http://localhost:8090/debug/pprof/heap
而后一样输入 top
命令查看函数使用状况,以下图:
其他的跟踪分析命令相似,就不一一分析了。
把上面在终端命令行下交互分析的数据进行可视化分析。
在前面可视化分析中,咱们了解到可视化最重要有 2 步:1.采集数据 2.图形化采集的数据。
在上面第三节 runtime/pprof 中,进入终端命令行交互操做,而后输入 web 命令,就能够生成一张 svg 格式的图片,用浏览器能够直接查看该图片。咱们用一样的方法来试一试。
go tool pprof http://localhost:8090/debug/pprof/profile?seconds=30
web
命令以下图:
果真生成了一个 svg 文件,在浏览器查看该图片文件,啥有用信息也没有,以下图:
为何没有有用信息?前面有讲到过,没有用户访问 http server ,须要的程序没有运行,一直阻塞在那里等待客户端的访问链接,因此 go tool pprof 只能采集部分代码运行的信息,而这部分代码又没有消耗多少 cpu。
那怎么办?
一个方法就是用 http 测试工具模拟用户访问。这里用 https://github.com/rakyll/hey 这个工具。
安装 hey:
go get -u github.com/rakyll/hey
安装完成后,进行 http 测试:
hey -n 1000 http://localhost:8090/pprof-test
同时开启另外一终端执行命令:
go tool pprof http://localhost:8090/debug/pprof/profile?seconds=120
等待 120s 后,采集信息完成,以下图:
输入 top
命令查看统计信息:
能够看到用户定义的一个最耗时函数是:main.cyclenum
。若是要查看这个函数最耗时部分代码,能够用 list cyclenum
命令查看。
咱们这里是要生成一张图片,因此输入 web
命令生成图片:
在浏览器上查看 svg 图片:
(图片较大,只截取了部分)
这张图完整的展现了 top
命令的信息。
执行命令:
go tool pprof -http=":8080" http://localhost:8090/debug/pprof/profile
同时开启另外一终端执行测试命令:
hey -n 200 -q 5 http://localhost:8090/pprof-test
上面 go tool pprof
执行完成后,会自动在浏览器打开一个 http 地址,http://localhost:8080/ui/,以下图:
(截取部分图片)
这样就能够在web浏览器上查看分析数据了。
用 http 测试框架 hey 访问,命令为:
hey -n 200 -q 5 http://localhost:8090/pprof-test
在压测的同时开启另外一终端执行命令:
go-torch -u http://localhost:8090
来生成火焰图。
运行命令时在终端输出了信息 :
Run pprof command: go tool pprof -raw -seconds 30 http://localhost:8090/debug/pprof/profile
能够看到 go-torch
的原始命令也是用到了 go tool pprof
上面这个命令默认生成了 torch.svg 的火焰图文件,以下:
(截取一部分图展现)
点击方块能够查看更详细信息: