go build 无文件_Go学习_30_Golang代码性能分析工具

Golang内置了一些性能分析工具,可以将性能分析的结果文件输出,我们可以使用图形化的工具查看分析结果,在使用这些工具之前,我们需要安装一些工具,以便于查看分析文件。

为了支持查看图形化分析结果,首先需要安装graphviz工具:

brew install graphviz

为了方便调用Golang的分析工具,我们需要将$GOPATH/bin加入到$PATH中去:

  • 在Windows中通过环境变量设置

  • 在Mac下,通过vim ~/.bash_profile打开设置文件,添加配置如下:

dcc278d646c81ef4bcdcc5b4d4fafa4b.png

uber提供了go-torch工具可以将分析结果文件以火焰图的方式进行展示,在go1.11之后的版本中go-torch被内置到了golang中,当然要是本地没有go-torch工具,可以通过以下步骤安装go-torch工具:

1. 安装go-torch

go get github.com/uber/go-torch

2. 下载并复制flamegraph.pl(可在https://github.com/brendangregg/FlameGraph下载)文件到$GOPATH/bin路径下。

golang通过将性能测试文件输出的方式给出性能测试的结果,我们可以通过go tool查看性能分析文件。

当我们想要对特定代码片段进行性能分析的时候,可以手动调用runtime/pprof下的API进行性能分析,runtime/pprof的API文档:

https://studygolang.com/pkgdoc

下面我们通过runtime.pprof对一段二维数组操作的代码片段进行性能检测:

首先是对二维数据的两个操作函数:

1d2e7f4420545bc8942fde409a57f1d5.png

分别对二维数组进行随机填充,并对二维数组的每一行进行加和操作。

然后编写使用runtime.pprof对目标代码片段的测试代码:

64c5037ba86ef5437596d2e9d93ca3fc.png

【代码说明】

1. CPUProfile测试代码需要放在待测试代码片段的前面,调用pprof.StartCPUProfile()函数开启pprof测试,我们知道golang的函数在执行完所有的代码之后,会调用函数内部定义的defer函数,所以在此处的defer函数中调用一下pprof.StopCPUProfile()来结束本次测试;

defer func() {    pprof.StopCPUProfile()}()// 也可以简写成defer pprof.StopCPUProfile()

2. 上面代码中,在待测试代码的后面有两段性能信息导出代码(堆栈信息导出、协程信息导出),这两部分的代码负责将pprof测试信息中的指标导出到profile文件中,所以要放在待测试代码片段的后面执行;

3. 上面代码中导出协程信息使用了pprof.Lookup(flagTag)函数,要是想要导出其他的性能flag信息,只需要给pprof.Lookup()函数传入不同的flag,支持的flag可以从下面的文件中查看:

https://golang.org/src/runtime/pprof/pprof.go

e21db14b212cda0720986e9d72144b71.png

编写好性能测试代码之后,我们就可以对待测试代码进行性能检测了,检测的步骤:

(1)build源代码文件生成可运行的二进制文件:

go build main.go

可以看到生成了一个可执行的二进制文件:

72611957616023988b7223b74db9561f.png

(2)运行二进制文件生成性能测试文件:

fa593c732b31f6cd4b362388d0bb3a52.png

可以看到输出了3个profile文件。

(3)查看profile文件,首先查看一下cpu.prof文件:

// 命令:go tool pprof  go tool pprof main cpu.prof

运行上面的命令之后,就会进入pprof的交互控制台:

fde49f191c2a9f25dd8a50de3a287b65.png

使用top命令查看cpu使用情况:

060b9c12e75fc01905f2a9a1a8693542.png

上图中我们可以看到本次此时过程中各个函数执行的情况,比如main函数中的fillMatrix执行的时间占了总执行时间的97.61%,花费了2450ms。

我们还可以通过list funcName来查看指定函数具体的耗时情况:

070276b4d1b52f89fb157c4a7f8a5dd8.png

list fillMatrix命令为我们打印出了fillMatrix函数中耗时最长的是二维数组的赋值。

同样的golang还允许我们以图形化的方式查看函数的耗时情况,使用svg命令可以将所有函数运行情况以svg格式输出:

ecf6d67161352df68aee7260d7df948f.png

当我们想要退出pprof工具的时候,可以使用exit命令:

3f5f089567d0947ea4c87159c786fcaa.png

我们可以将该svg图拖拽到浏览器中查看:

6d490aa4a116a69fdeb4be5330922048.png

上图中红色矩形越大的表示CPU耗时越长,箭头表示整个程序执行的顺序关系。

下面我们使用go-torch查看一下函数执行情况的火炬图,首先使用go-torch命令生成火炬图的:

e83a65e338ce9a6bdd18048546ea4034.png

上面的命令生成了一张torch.svg的图片文件,我们将其拖拽到浏览器中进行查看:

18921ac54d9ba36a56d788399260cf3c.png

将光标指向不同的火焰柱状图可以查看到不同函数执行是消耗的CPU时间情况。

同样的我们也可以使用命令查看mem.prof中各个函数在执行的过程中对内存的占用情况:

go tool pprof main mem.prof

c8afac2269b81d61e40ab66f9aea4e8c.png

上图中我们可以看到二维数据占用了绝大多数的内存。

在性能测试的过程中,有时候我们需要查看一下我们的变量在系统发生GC之后,垃圾变量是否可以被成功的回收,我们可以在输出mem.prof文件内容之前,手动触发一次GC:

f44c2e168830b8849400b16637288bfc.png

按照上面的命令,重新build二进制文件,并运行新的二进制文件,生成mem.prof文件,并进行查看:

1bcd43a1a7608c89ed080deebd67f952.png

我们发现在触发了GC之后,内存占用明显的降低了,从之前的1.49G降低到了1.72M,说明我们声明的变量是GC友好的,可以被系统成功的回收。

上面的测试方式适合我们在开发的过程中对代码片段进行性能检测,而对于线上运行的代码,我们不可能让线上程序一直输出测试文件,这样会影响到线上业务,不过pprof同样提供了线上代码性能测试的方法,运行我们通过http请求对线上任务进行一定时长的采样。

使用pprof对线上业务进行性能采样的步骤和要求:

  • 在应用程序中导入 "net/http/pprof"的包,并启动http server

  • 通过http://:/debug/pprof访问目标服务器

  • 使用下面的命令开始对线上业务进行采样

// pprof进行采样// seconds参数可以指定采样时长,默认采样时间30sgo tool pprof http://:/debug/pprof/profile?seconds=10// 同样可以使用go-torch进行线上采样生成火焰图go-torch -seconds 10 http://:/debug/pprof/profile

在gin框架中使用pprof进行性能数据采样测试

为了测试pprof和go-torch对线上代码性能的测试,下面首先使用gin框架搭建一个简单的http服务:

e37556ce327321a16d9c3182f552e242.png

该Http服务提供了两个访问接口,/ 和 /fb,后者循环生成多次斐波那契数列。我们直到使用pprof对线上业务进行性能采样测试的时候,必须启动一个golang内置的http server,那么我们通过gin框架也可以满足这个条件吗?我们查看gin的Run(listenPort)源码:

be01fc179846d6bacc5379594b69cb49.png

从上面的gin源码可以看到gin的Run函数内部其实也是使用http包进行Http Server的启动。其实不止gin框架,我们常用的beego和iris框架,追踪源码我们会发现,它们也是通过http包启动server服务的,因此当我们使用这些框架进行http server开发,同样可以使用pprof进行线上业务的采样测试。但是在正式使用pprof对gin框架的http server进行测试之前,我们还需要安装gin对pprof的封装包:

go get github.com/DeanThompson/ginpprof

并在程序中开启ginpprof服务,如上图代码中。

编写完gin的服务器之后,我们通过命令启动http服务:

07addcb02bf989ea1042f0dfc86ce2ae.png

在浏览器中进行访问:

a5aba908cf73e50edf9e4ae798b81b4e.png

服务启动成功。

请求连接就可以看到下面的测试网页:

9a0ec9c3bf7af809307ba15731d99484.png

点击就可以查看到不同的测试数据。

我们也可以通过命令行进行性能数据的采样:

7ae35fd7e4b142000208bd98c3a77d59.png

上面进行了20s的性能数据采样,当采样结束之后,命令行会自动进入pprof交互模式,这时我们就可以通过命令进行文件查看了:

95c79f460f132d1e4d0924f1017640b9.png

同样的也可以通过go-torch进行采样分析:

ed7a84110934053652a052dd6e9436fc.png

同样的,在指定的采样时间结束之后,go-torch就会结束采样,并将svg的文件输出到命令行文件目录下,我们可以在本地找到这个torch.svg文件,并将其拖拽到浏览器中查看:

706572aaf258df5ea4b3633f77532cd7.png

在iris框架下使用pprof进行性能数据的采样测试

和gin框架一样,我们首先需要搭建一个iris的http服务(下面使用了v12版本的iris):

1e4ce50e70183b8c92b2c8b345eca2fd.png

和golang内置的http server以及gin框架有所不同,iris下使用pprof工具,我们需要手动添加两个访问接口,添加完上述代码之后,运行iris服务:

go run main.go

在浏览器中测试访问接口:

7f69ea3db174893248442bd81e0fd9af.png

服务启动成功。

同样的我们可以通过url来查看pprof的性能数据:

fafd5758e1e8f8766d09169fa481d614.png

通过命令行来查看pprof采样数据:

go tool pprof http://127.0.0.1:8081/debug/pprof/heap?seconds=10

在命令行中输入上面的请求,会采样最近10s内线上服务堆栈使用的情况,在输入命令之后,会立即dump并进入到pprof的交互控制台(这和查看profile不太一样):

bca0ae3aa12ce378fdc0212f9b38edcb.png

查看一下iris的middleware/pprof包中的New方法,从源码我们可以看到,iris内部也是使用了golang内置的net/http/pprof进行性能数据的采样,除了profile和heap,我们还可以查看的数据指标也可以从源码中看到:

5e96fc9b7ce5eb17a98b882a5f4129ac.png

同样的使用go-torch对性能数据进行采样并输出火焰图:

ca63ed0d4b3ea1e4e62f899bd5d7859f.png

将火焰图拖拽到浏览器中查看:

44fcccd75cc91106d7b0558109130fa4.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值