pprof性能优化

Go性能优化主要方面

  • CPU profile:报告程序的 CPU 使用情况,按照一定频率去采集应用程序在 CPU 和寄存器上面的数据
  • Memory Profile(Heap Profile):报告程序的内存使用情况
  • Block Profiling:报告 goroutines 不在运行状态的情况,可以用来分析和查找死锁等性能瓶颈
  • Goroutine Profiling:报告 goroutines 的使用情况,有哪些 goroutine,它们的调用关系是怎样的

工具型应用

  • 使用背景:应用程序是运行一段时间就结束退出类型;最好的办法是在应用退出的时候把 profiling 的报告保存到文件中,再进行分析
  • 使用runtime/pprof库;工具型应用运行数据进行分析
//CPU性能分析
//开启
pprof.StartCPUProfile(w io.Writer)
//关闭
pprof.StopCPUProfile()
//示例
var isCPUPprof bool
flag.BoolVar(&isCPUPprof, "cpu", false, "turn cpu pprof on")
flag.Parse()
	if isCPUPprof {
		file, err := os.Create("./cpu.pprof")
		if err != nil {
			fmt.Printf("create cpu pprof failed, err:%v\n", err)
			return
		}
		pprof.StartCPUProfile(file)
		defer pprof.StopCPUProfile()
	}
//使用go tool pprof 工具进行CPU性能分析

//内存性能优化;记录程序的堆栈信息
pprof.WriteHeapProfile(w io.Writer)
//示例
var isMemPprof bool
flag.BoolVar(&isMemPprof, "mem", false, "turn mem pprof on")
flag.Parse()
if isMemPprof {
		file, err := os.Create("./mem.pprof")
		if err != nil {
			fmt.Printf("create mem pprof failed, err:%v\n", err)
			return
		}
		pprof.WriteHeapProfile(file)
		file.Close()
	}
//使用go tool pprof工具进行内存性能分析,默认是使用-inuse_space进行统计,还可以使用-inuse-objects查看分配对象的数量

服务型应用

  • 使用背景:如果应用程序是一直运行的,比如 web 应用,那么可以使用;
  • 使用的库是: net/http/pprof;服务型应用运行时数据进行分析;它能够在提供 HTTP 服务进行分析。
//如果使用了默认的http.DefaultServeMux(通常是代码直接使用http.ListenAndServe(“0.0.0.0:8000”, nil)),只需要在web server端代码中匿名导入net/http/pprof
//如果使用自定义的 Mux,则需要手动注册一些路由规则:
r.HandleFunc("/debug/pprof/", pprof.Index)
r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
r.HandleFunc("/debug/pprof/profile", pprof.Profile)
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
//如果你使用的是gin框架,那么推荐使用"github.com/DeanThompson/ginpp

分析结果查看

命令行

go tool pprof 生成的二进制文件  //进入交互界面
//在交互界面输入top3来查看程序中占用CPU前3位的函数
(pprof) top3
Showing nodes accounting for 100.37s, 87.68% of 114.47s total
Dropped 17 nodes (cum <= 0.57s)
Showing top 3 nodes out of 4
      flat  flat%   sum%        cum   cum%
    42.52s 37.15% 37.15%     91.73s 80.13%  runtime.selectnbrecv
    35.21s 30.76% 67.90%     39.49s 34.50%  runtime.chanrecv
    22.64s 19.78% 87.68%    114.37s 99.91%  main.logicCode
/*
flat:当前函数占用CPU的耗时
flat%::当前函数占用CPU的耗时百分比
sun%:函数占用CPU的耗时累计百分比
cum:当前函数加上调用当前函数的函数占用CPU的总耗时
cum%:当前函数加上调用当前函数的函数占用CPU的总耗时百分比
最后一列:函数名称
*/
//可以使用list 函数名命令查看具体的函数分析,例如执行list logicCode查看我们编写的函数的详细分析。
(pprof) list logicCode
Total: 1.91mins
ROUTINE ================ main.logicCode in .../runtime_pprof/main.go
    22.64s   1.91mins (flat, cum) 99.91% of Total
         .          .     12:func logicCode() {
         .          .     13:   var c chan int
         .          .     14:   for {
         .          .     15:           select {
         .          .     16:           case v := <-c:
    22.64s   1.91mins     17:                   fmt.Printf("recv from chan, value:%v\n", v)
         .          .     18:           default:
         .          .     19:
         .          .     20:           }
         .          .     21:   }
         .          .     22:}

//直接输入web;过svg图的方式查看程序中详细的CPU占用情况;需要安装graphviz图形化工具。
//下载graphviz 将graphviz安装目录下的bin文件夹添加到Path环境变量中。 在终端输入dot -version查看是否安装成功。

图形界面

//安装go-torch;他可以直接读取 golang profiling 数据,并生成一个火焰图的 svg 文件。
go get -v github.com/uber/go-torch
/*
从http://localhost:8080/debug/pprof/profile获取 profiling 数据。它有三个常用的参数可以调整:
-u –url:要访问的 URL,这里只是主机和端口部分
-s –suffix:pprof profile 的路径,默认为 /debug/pprof/profile
–seconds:要执行 profiling 的时间长度,默认为 30s
*/

/*
要生成火焰图,需要事先安装 FlameGraph工具
-下载安装perl:https://www.perl.org/get.html
-下载FlameGraph:git clone https://github.com/brendangregg/FlameGraph.git
- 将FlameGraph目录加入到操作系统的环境变量中。
- Windows平台需要把go-torch/render/flamegraph.go文件中的GenerateFlameGraph按如下方式修改,然后在go-torch目录下执行go install即可。
*/
// GenerateFlameGraph runs the flamegraph script to generate a flame graph SVG. func GenerateFlameGraph(graphInput []byte, args ...string) ([]byte, error) {
flameGraph := findInPath(flameGraphScripts)
if flameGraph == "" {
	return nil, errNoPerlScript
}
if runtime.GOOS == "windows" {
	return runScript("perl", append([]string{flameGraph}, args...), graphInput)
}
  return runScript(flameGraph, args, graphInput)
}

/*
使用wrk([地址](https://github.com/wg/wrk))进行压测:go-wrk -n 50000 http://127.0.0.1:8080/book/list 在上面压测进行的同时,打开另一个终端执行go-torch -u http://127.0.0.1:8080 -t 30,30秒之后终端会初夏如下提示:Writing svg to torch.svg,然后使用浏览器打开torch.svg就能看到火焰图了。
*/

注意:

Profiling 一般和性能测试一起使用,只有应用在负载高的情况下 Profiling 才有意义。

go test -bench . -cpuprofile=cpu.prof //执行测试的同时,也会执行 CPU profiling,把结果保存在 cpu.prof 文件中
go test -bench . -memprofile=./mem.prof //执行测试的同时,也会执行 Mem profiling,把结果保存在 mem.prof 文件中

猜你喜欢

转载自blog.csdn.net/wzb_wzt/article/details/107429662