这是我参与「第五届青训营 」伴学笔记创造活动的第 9 天

前语

本文主要内容为Go功能调优、功能剖析东西——pprof的介绍、pprof的采样进程以及原理解析。

简介

在实践项目中,咱们都知道优化很重要,在工作中伴随着迭代的开发,代码的优化要适度进行不要过度,下面是优化的准则可供参考。

功能优化、调优准则:

  • 要依托数据而不是猜想
  • 要定位最大瓶颈而不是细枝末叶
  • 不要过早优化
  • 不要过度优化

功能剖析东西

咱们希望知道应用在什么地方耗费了多少CPUMemory,有没有什么东西能够检测?

pprof就是这样的东西,pprof可用于可视化和剖析功能剖析数据的东西,下面将对pprof进行介绍以及简单的使用介绍。

pprof是一个强大的功能剖析东西,能够捕捉到多维度的运转状况的数据,Go在语言层面集成了profile采样东西,在程序运转进程中能够获取cpuheapblocktraces等履行信息,这些会涉及到runtime/pprofnet/http/pprof等包,获取profile数据最有两种形式:web形式与profile文件生成形式。

Go 性能优化分析神器——pprof| 青训营笔记

pprof实战

项目建立

建立pprof实践项目,这儿使用的是github上一个开源项目,这个项目提前埋入了一些炸弹代码,产生可观测的功能问题,运转该项目会占用1CPU中心和超越1GB的内存。

开源项目地址:github.com/wolfogre/go…

将项目clone下来之后,在终端输入go run main.go即可运转项目。

目标查看

翻开浏览器,输入地址 http://localhost:6060/debug/pprof 即可,如图。

Go 性能优化分析神器——pprof| 青训营笔记

从页面中能够查到,内存、block、协程、堆等分配的状况以及锁的操作等。

CPU

首要看一下CPU的运转状况,翻开电脑自带的活动管理器,能够看到此项目在我的电脑上占了48%的CPU。

Go 性能优化分析神器——pprof| 青训营笔记

pprof在每运转一段时刻后,就会把运转信息输出到文件中,咱们能够经过指令来获取文件。

在终端中输入指令,获取文件:

go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"

Go 性能优化分析神器——pprof| 青训营笔记

topN

指令:top

用于查看占用资源最多的函数

Go 性能优化分析神器——pprof| 青训营笔记

参数阐明:

  • flat: 当时函数自身的履行耗时
  • flat%flatCPU总时刻的份额
  • sum%: 上面每一行的flat%总和
  • cum: 当时函数自身加上其周期函数的总耗时
  • cum%cumCPU总时刻的份额

从图中能够看到,Flat列有的是0,有的不是0,那么Flat在什么状况下等于Cum?什么状况下等于0呢?

根据上述参数阐明,能够知道:

  • Flat == Cum,阐明函数中没有调用其他函数
  • Flat == 0,阐明函数中只有其他函数的调用

经过top指令,得出Eat函数是最消耗CPU的,下面介绍怎么定位到代码的详细行。

list

指令:list

能够根据指定的正则表达式查找代码行

Go 性能优化分析神器——pprof| 青训营笔记

输入指令list Eat,从输出成果里能够看到对应的文件为tiger.go,并且详细的代码行为24行的for循环。

web

有时候根据指令行查看成果不是很直观,pprof还供给了可视化的查看方式。

指令: web

将调用关系生成可视化文件,能够输出可视化调用量以及每个节点的资源占用数据。

Go 性能优化分析神器——pprof| 青训营笔记

找到代码进行更改,将循环次数改小一些,再次发动项目,查看资源占用状况,能够发现CPU现已没有那么高了。

Go 性能优化分析神器——pprof| 青训营笔记

Go 性能优化分析神器——pprof| 青训营笔记

Heap

经过代码的改造,能够发现CPU的问题现已处理了,可是内存使用仍是很高。

Go 性能优化分析神器——pprof| 青训营笔记

这次直接以可视化的办法查看,输入以下指令,翻开堆内存的占用状况:

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"

翻开之后,会呈现一下界面:

Go 性能优化分析神器——pprof| 青训营笔记

从上图咱们一眼就能够看出,Mouse这个目标的Steal办法占用的内存最多。

翻开View->Source视图,还能够看到详细的代码文件以及对应的行数。

Go 性能优化分析神器——pprof| 青训营笔记

找到对应的代码,将代码进行注释,然后看下资源占用状况。

注释掉mouse.go文件的第50行。

Go 性能优化分析神器——pprof| 青训营笔记

重新运转项目,查看资源占用现已很低了。

Go 性能优化分析神器——pprof| 青训营笔记

采样阐明,SAMPLE菜单中有几个选项,对应阐明如下:

  • alloc_objects: 程序累计请求的目标数
  • alloc_space: 程序累计请求的内存大小
  • inuse_objects: 程序当时持有的目标数
  • inuse_space: 程序当时占用的内存大小

协程

goroutine泄露也会导致内存泄露

以可视化的办法查看,输入以下指令,翻开堆内存的占用状况:

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"

Go 性能优化分析神器——pprof| 青训营笔记

火焰图阐明:

  • 由上到下标识调用次序
  • 每一块代表一个函数,越长代表占用CPU时刻更长
  • 火焰图是动态的,支撑点击块进行剖析

切换到Source视图,查看代码详细位置。

Go 性能优化分析神器——pprof| 青训营笔记

能够看出wolf.go文件里的第34行,协程里进行了睡眠30s,修正此处代码即可修正该问题。

mutex

经过pprof查看锁相关问题,比方加锁时刻长等。

履行指令:

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"

输出界面如下:

Go 性能优化分析神器——pprof| 青训营笔记

切换到代码视图:

Go 性能优化分析神器——pprof| 青训营笔记

能够发现,wolf.go文件里在开释锁前,进行了睡眠操作,对此处代码进行修正即可修正问题。

block

查看代码中是否存在堵塞,履行指令:

go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"

输出界面如下:

Go 性能优化分析神器——pprof| 青训营笔记

切换到Source视图,能够看到cat.go文件里存在堵塞行为:

Go 性能优化分析神器——pprof| 青训营笔记

同样的,经过top指令也能够看到存在问题的文件。

Go 性能优化分析神器——pprof| 青训营笔记

pprof原理

下面介绍一下pprof的采样进程以及实现原理。

CPU

采样目标:函数调用和他们占用的时刻

采样率:100次/秒,固定值

采样时刻:从手动发动到手动结束

Go 性能优化分析神器——pprof| 青训营笔记

采样详细流程如下:

Go 性能优化分析神器——pprof| 青训营笔记

流程阐明:

  • 操作体系:每10ms向进程发送一次SIGPROF信号
  • 进程:每次接收到SIGPROF信号会记载调用仓库
  • 写缓冲:每100ms读取现已记载的调用栈并写入输出流

堆内存

堆内存采样进程如下:

  • 采样程序经过内存分配器在堆上分配和开释内存,记载分配/开释的大小和数量
  • 采样率:每分配512KB记载一次,可在运转开头修正,1为每次分配均记载
  • 采样时刻:从程序运转开端到采样时
  • 采样目标:alloc_space, alloc_objects, inuse_space, inuse_objects
  • 计算方式:inuse = alloc – free

协程&线程创立

协程和线程创立在实现上十分的类似,都是会在STW之后,遍历所有goroutine/所有线程的列表并输出仓库,最后Start The World持续运转。这个采样是立刻触发的全量记载,能够经过比较两个时刻点的差值来得到某一时刻段的目标。

协程(Goroutine)

记载所有用户建议且在运转中的goroutine(即进口非runtime开头的)runtime.main的调用栈信息

线程创立(ThreadCreate)

记载程序创立的所有体系线程的信息

协程和线程创立的采样流程如下:

Go 性能优化分析神器——pprof| 青训营笔记

Block&Mutex

堵塞和锁竞争这两个目标在流程和原理也十分类似,这两个采样记载的都是对应操作产生的调用栈、次数和耗时,不过这两个目标的采样率意义并不相同。

堵塞操作的采样率是一个”阈值“,消耗超越阈值时刻的堵塞操作才会被记载,1为每次操作都会记载。

锁竞争的采样率是一个”份额“,运转时会经过随机数来只记载固定份额的锁操作,1为每次操作都会记载。

堵塞操作的采样操作:

  • 采样堵塞操作的次数和耗时
  • 采样率:堵塞耗时超越阈值的才会被记载,1为每次堵塞均记载

锁竞争的采样操作:

  • 采样争抢锁的次数和耗时
  • 采样率:只记载固定份额的锁操作,1为每次加锁均记载

堵塞和锁竞争的采样流程如下:

Go 性能优化分析神器——pprof| 青训营笔记

总结

本文主要内容为Go功能调优、功能剖析东西——pprofpprof供给了指令行、可视化等排查问题手段,本文经过代码实践运转排查代码中存在的功能问题,经过pprof能够方便快捷的排查代码中呈现的CPU、内存、仓库、协程、block、锁等各个方面的问题。

尽管比如比较简单,可是经过这个比如能够使咱们快速上手pprof东西的使用办法,为之后排查问题、功能优化奠定了良好的根底。

引证

功能优化剖析东西

功能调优实战事例