TiDB性能分析工具——PProf

【是否原创】是
【首发渠道】TiDB 社区
【正文】

背景

数据库的性能永远是数据库开发过程中最为关注的问题,所以在TiDB开发过程中,要经常对数据库性能进行测试,在完成功能的基础上保证性能的稳定,如果性能出现明显波动和大幅度下降,则需要定位造成性能下降的原因,同样的,当需要去优化数据库性能,定位性能瓶颈时,也需要定位到具体的方法进行优化。那么这个过程中,我们如何进行性能分析,迅速的定位到问题方法,就可以使用到Profiling工具了。

Profiling工具,是一种性能分析工具,可以跟踪程序在运行中的方法调用栈,并统计相关的资源开销和时间消耗,例如CPU,内存等资源,通过分析方法与方法之间的调用关系和资源开销可以帮助我们迅速的定位到资源消耗最大的方法,快速找到问题的关键。

当然TiDB本身进行分析的手段比较多,内置各种监控,但是在本地源码开发的过程中,可以推荐使用Profiling工具,一是启用这种工具非常简单,不需要过多的操作,二是Profiling的指标比较齐全,监控更为细致,分析起来非常方便。

TiDB中启用Profiling工具

不同语言都有自己的Profiling工具,TiDB是使用Golang实现的,所以可以直接使用Golang的Profiling工具来进行分析,那么这里本文选择的是PProf。

PProf是Golang提供的代码性能分析工具,可以直接生成代码分析报告,可以采用命令式交互进行查看,也可以进行可视化展示。这里不做过多介绍,直接看下如何将PProf引入到TiDB中。

引用 pprof 包

PProf 包有两种:

  1. 服务型应用 _ “net/http/pprof” 包,专用于采集web服务运行数据的分析
  2. 工具型应用 “runtime/pprof” 包,专用于采集应用程序运行数据的分析
    数据库本身是一种服务型应用,需要对外暴露服务,所以选择”net/http/pprof”包。
    程序中引入 net/http/pprof 包,可以直接在主程序的最前面加上调用语句,只需要一句话就能启动 PProf,十分方便。如下:
    Code: PProf

所以在TiDB中,先找到主程序入口,tidb/tidb-server/main.go 中的main() 方法,插入三行代码,会自动引入PProf包,然后正常启动即可。

通过Web界面查看

成功启动程序后,可以直接访问:http://host:8005/debug/pprof/ 来查看


其中有很多的子文件可以打开,下面也有相应的介绍:

allocs : 过去所有内存分配的样例

block : 导致阻塞同步的堆栈跟踪

cmdline : 当前程序的命令行调用

goroutine : 当前所有 goroutine 的堆栈跟踪

heap : 活动对象的内存分配情况,可以指定 gc Get 参数,以便在获取堆样本之前运行 gc

mutex : 互斥锁竞争者的堆栈跟踪

profile : CPU配置文件。您可以在seconds GET参数中指定持续时间,获取配置文件后,使用go tool pprof命令来查看配置文件。

threadcreate : 导致创建新OS线程的堆栈跟踪

trace : 跟踪当前程序的执行。您可以在seconds GET参数中指定持续时间。获取跟踪文件后,使用go tool trace命令来调查跟踪。

可以看到PProf进行跟踪和监控的指标非常多,除了常用的CPU,内存开销,还包括线程,goruntine,互斥锁等堆栈跟踪,一般在普通的性能分析中是用不到这么多指标的,但是针对于不同的场景和需求,大家可以自己选择并进行查看。

使用交互式命令行查看

如果我们想要观察一段时间内程序各个指标的值,可以输入以下指令:

go tool pprof http://host:8005/debug/pprof/profile?seconds=60


执行该命令后等待 60s 即可进入到交互式命令模式(后面的 profile 可以换成其他的参数,例如 heap,mutex 等等,seconds表示所要观察的时间。)

进入交互式命令模式后可以输入一系列指令进行详细的记录查看,例如 Top10 查看耗时最长的前10个记录,其余的指令可以通过 pprof help 来查看详情,这里不一一介绍。


flat : 给定函数上的运行耗时

flat% : 同上的CPU运行耗时的总比例

sum% : 给定函数累计使用 CPU 总比例

cum ; 当前函数加上它之上的调用运行总耗时

cum% : 同上的CPU运行耗时总比例

最后一列 : 函数名

通过 web 指令查看可视化界面

如果想要查看图形化界面,则需要安装 Graphviz

sudo apt-get install graphviz

安装 Graphviz后,在交互命令行中输入 web 即可,可以通过可视化图形来查看方法之间的调用关系和每一个方法的资源开销与时耗。


其中每一个方块都代表一个方法,方法之间就是调用关系,方块大小则表示该方法的资源开销和时耗越大,所以通过每一个方块大小和内容,可以很快的定位到资源消耗较大的方法或者是异常的方法。

其实通过这种方式,在初学TiDB源码的时候,可以查看这种关系图,来迅速学习TiDB的代码架构,方法调用流程和功能,还0包括关键函数位置,非常适合新手进行源码学习。

除了这种流程图式的可视化展示,还有一种可视化展示-火焰图。

使用 go-torch 工具生成火焰图

go-torch 是 uber 开源的一个工具,可以直接读取 pprof 的 profiling 数据,生成一个火焰图 svg 的文件,通过浏览器即可打开,查看整个火焰图(该图为可交互的)

地址:GitHub - uber-archive/go-torch: Stochastic flame graph profiler for Go programs

安装 go-torch 和 FlameGraph

go get github.com/uber/go-torch

cd $GOPATH/src/github.com/uber/go-torch

git clone https://github.com/brendangregg/FlameGraph.git

cp FlameGraph/flamegraph.pl /usr/local/bin


注意: 这里直接尝试一下 go-torch 命令,如果报错 command not found 则需要自己编译

cd $GOPATH/src/github.com/uber/go-torch

go build -----生成可执行文件

cp go-torch /usr/local/bin


使用 go-torch 生成 svg 文件

go-torch 的具体指令可以通过 go-torch -h 来查看

go-torch -u http://host:8005 -t 60 -f cpu.svg


-u 指定相关 url 当没有后缀的时候 默认为 http://localhost:8080/debug/pprof/profile

-t 指定监控的时间为 60s

-f 指定文件名,当前目录下生成 cpu.svg

查看火焰图

当生成 svg 文件后,我们可以直接将其用浏览器打开(将文件拖到浏览器里面)

火焰图调用顺序从下往上,宽度代表其占用的时间,由于火焰图是可交互的,可以用鼠标点击每一个小方块进去看其具体的信息和其内部函数的调用。


由于TiDB整个系统较为庞大,文章篇幅有限,本文并没有过多介绍的PProf分析TiDB的过程和结果,只是介绍了如何使用PProf,那么大家可以在了解后,本地进行操作和分析,方便大家进行TiDB的开发。

总结

  1. 通过PProf工具可以查看一段时间内TiDB中每个函数的资源占用率,最快的速度找到开销异常的函数并进行定位,找到性能问题的原因。
  2. 可以将多个版本的TiDB(开发前和开发后)进行性能分析,通过Profiling工具生成的图进行直接对比,可以更直观的发现改动代码对于每个模块造成的影响和两个版本的差异。
  3. 通过函数调用关系图,可以帮我们更快的了解TiDB代码结构和方法调用栈,适合新手学习,寻找关键函数。
2赞

感谢分享!