Go程序性能分析方法(一文全解)

前言

golang作为一门高效的语言,性能监控和调试非常重要,如何进行性能监控和分析是优化的关键。

Go语言项目中的性能优化主要有以下几个方面:

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

go语言提供包

  • runtime/pprof:采集工具型应用运行数据进行分析
  • net/http/pprof:采集服务型应用运行时数据进行分析

采集方式

pprof开启后,每隔一段时间(10ms)就会收集下当前的堆栈信息,获取格格函数占用的CPU以及内存资源;最后通过对这些采样数据进行分析,形成一个性能分析报告。
引入包

import "runtime/pprof"

使用方法

pprof.StartCPUProfile(w io.Writer) //开启,向一个io中写入cpu信息
pprof.WriteHeapProfile(w io.Writer) //向一个io中写入内存信息
pprof.StopCPUProfile() //停止,写入完成
命令模式

将数据写入到文件中
通过 go tool pprof [文件名] 命令查看使用

我们可以在交互界面输入top3来查看程序中占用CPU前3位的函数:
在这里插入图片描述
其中:

  • flat:当前函数占用CPU的耗时
  • flat%:当前函数占用CPU的耗时百分比
  • sun%:函数占用CPU的耗时累计百分比
  • cum:当前函数加上调用当前函数的函数占用CPU的总耗时
  • cum%:当前函数加上调用当前函数的函数占用CPU的总耗时百分比
  • 最后一列:函数名称

也可以通过list 函数名查看函数的信息
在这里插入图片描述
通过分析发现大部分CPU资源被26行占用

调度图

输入web在网页中查看调度图,输入pdf生成一个pdf文件
需要安装工具graphviz
在这里插入图片描述
关于图形的说明: 每个框代表一个函数,理论上框的越大表示占用的CPU资源越多。 方框之间的线条代表函数之间的调用关系。 线条上的数字表示函数调用的次数。 方框中的第一行数字表示当前函数占用CPU的百分比,第二行数字表示当前函数累计占用CPU的百分比。

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

import _ "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/ginpprof"。

不管哪种方式,你的 HTTP 服务都会多出/debug/pprof endpoint,访问它会得到类似下面的内容:
在这里插入图片描述
这个路径下还有几个子页面:

  • /debug/pprof/profile:访问这个链接会自动进行 CPU profiling,持续 30s,并生成一个文件供下载
  • /debug/pprof/heap: Memory Profiling 的路径,访问这个链接会得到一个内存 Profiling 结果的文件
  • /debug/pprof/block:block Profiling 的路径
  • /debug/pprof/goroutines:运行的 goroutines 列表,以及调用关系

go-torch方法

火焰图(Flame Graph)是 Bredan Gregg 创建的一种性能分析图表,因为它的样子近似 🔥而得名。上面的 profiling 结果也转换成火焰图,如果对火焰图比较了解可以手动来操作,不过这里我们要介绍一个工具:go-torch。这是 uber 开源的一个工具,可以直接读取 golang profiling 数据,并生成一个火焰图的 svg 文件。
安装

 go get -v github.com/uber/go-torch

火焰图 svg 文件可以通过浏览器打开,它对于调用图的最优点是它是动态的:可以通过点击每个方块来 zoom in 分析它上面的内容。

火焰图的调用顺序从下到上,每个方块代表一个函数,它上面一层表示这个函数会调用哪些函数,方块的大小代表了占用 CPU 使用的长短。火焰图的配色并没有特殊的意义,默认的红、黄配色是为了更像火焰而已。

go-torch 工具的使用非常简单,没有任何参数的话,它会尝试从http://localhost:8080/debug/pprof/profile获取 profiling 数据。它有三个常用的参数可以调整:

-u –url:要访问的 URL,这里只是主机和端口部分
-s –suffix:pprof profile 的路径,默认为 /debug/pprof/profile
–seconds:要执行 profiling 的时间长度,默认为 30s

FlameGraph工具

要生成火焰图,需要事先安装 FlameGraph工具,这个工具的安装很简单(需要perl环境支持),只要把对应的可执行文件加入到环境变量中即可。

  1. 下载安装perl:https://www.perl.org/get.html
  2. 下载FlameGraph:git clone https://github.com/brendangregg/FlameGraph.git
  3. 将FlameGraph目录加入到操作系统的环境变量中。
  4. Windows平台的同学,需要把go-torch/render/flamegraph.go文件中的GenerateFlameGraph按如下方式修改,然后在go-torch目录下执行go install即可。go-torch命令就是调用这个生成的文件,最好给bin目录配置环境变量
// 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压测工具(go-wrk)

推荐使用https://github.com/wg/wrkhttps://github.com/adjust/go-wrk

go-torch使用

启动需要监控的程序,运行wrk压测,在终端中执行命令,30s后会在当前目录生成 torch.svg 文件

go-torch -u http://127.0.0.1:8080 -t 30

用浏览器打开这个文件,如下图
在这里插入图片描述
这里是一个典型失败的案例,任何性能测试分析,必须要在高压环境下才有意义,如下图。
在这里插入图片描述
火焰图的y轴表示cpu调用方法的先后,x轴表示在每个采样调用时间内,方法所占的时间百分比,越宽代表占据cpu时间越多。通过火焰图我们就可以更清楚的找出耗时长的函数调用,然后不断的修正代码,重新采样,不断优化
当然,go-torch也能够对内存进行监控,只需要在命令的最后面添加,
–colors=mem
效果图如下
在这里插入图片描述

Metricbeat 监控

除了上面的方法外,我们还能够开启自定义监控
使用expvar包

import "expvar"

expvar包的具体用法可以参考官网的文档,这里就不细讲了。
使用expvar包监控就不能向上面两种一样简单方便了,需要我们自己结果数据的显示问题,网上的常用方法是使用elastic家族的三大件
Metricbeat + ElasticSearch + Kibana
效果非常的漂亮
在这里插入图片描述
elastic家族系列下载地址:https://www.elastic.co/cn/
这里贴出使用方法:https://www.cnblogs.com/mrblue/archive/2019/05.html
可惜可芭纳只有英文的,使用很是费劲,且吾能力有限,不懂破解,只能望而兴叹。

自定义方法

这里介绍一种吾借助expvar包实现的监控方法。吾对前端实在一无所知,故界面很low,还是借助模板做出来的,本想直接将json传到前端,怎奈,吾前端能力有限,呜呼哀哉~~~

只需要导入包

import "gitee.com/yutiandou/wdtools/wdsys"

再执行下面的方法就可以了(自动进入协程中执行),

  • 第一个参数是地址端口
  • 第二个参数是 间隔多长时间扫描系统,如果是发布的程序最好去掉监控或者将时间设长点。
wdsys.StartMonitoringToHttp(":8000", time.Second*3)

这样会自动采集数据,并保留最近10条数据,可以通过url:/debug访问,如下图
在这里插入图片描述
在这里插入图片描述
我只实现了常用的十几种数据显示,如电脑内存使用情况,堆栈信息,gc情况,下图中的是还没实现了。需要查看这些数据的童鞋,可以自己实现一下,当做娱乐消遣。
在这里插入图片描述
除了上面的信息外,还可以借助工具包中的其他函数,获取系统其他信息。如下截图。
在这里插入图片描述
通过上面的6个api可以拉取系统的
本地ip地址,Cpu使用率,逻辑盒数,cpu负载,系统磁盘的分区信息,系统软硬件信息和下图
在这里插入图片描述
更多wdtools包使用方法参考吾之码云:https://gitee.com/yutiandou/wdtools

未完待续。。。。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值