在项目开发中,经常会遇到程序启动时间过长、CPU 使用率过高等问题,这个时候需要依靠性能分析工具来定位性能的消耗点。本文介绍三个常用的工具的入门级使用及图形化方法,供大家参考。
本文介绍 Perf、gprof 和 Valgrind 三个性能分析工具,及其分析结果图形化的方法,旨在让大家更快的上手使用工具。出于篇幅的限制,本文不会对每种工具的使用参数及结果分析做详细的介绍,只做入门级的使用说明,更多详细的说明大家请 Google 一下。
每个工具的介绍会分成简介、使用说明、图形化方法三个部分。
每种工具的结果都会基于下面这段代码:
这段代码在普通 PC 上执行了 31s,最大 CPU 使用率为 8.3%
Perf
1.1 简介
Perf 是内置于 Linux 内核源码树中的性能剖析(profiling)工具。其基于事件采样原理,以性能事件为基础,常用于性能瓶颈的查找与热点代码的定位。
1.2 使用
perf 的使用可以分为两种方式:
1.直接使用 perf 启动服务
2.挂接到已启动的进程
第一种方式不需要 root 权限,第二种方式需要 root 权限
基于入门级使用这一前提,直接介绍一下使用方式:
perf record -e cpu-clock -g ./run
或者
perf record -e cpu-clock -g -p 4522
使用 ctrl+c 中断 perf 进程,或者在程序执行结束后,会产生 perf.data 的文件,使用
perf report
会产生结果分析,如图
1.3 图形化方法
perf 的结果可以生成火焰图。生成火焰图需要借助 Flame Graph
Flame Graph 项目位于 GitHub:Flame Graph
clone 代码或者直接下载压缩包到服务器上。以压缩包为例,是一个命名为:FlameGraph-master.zip 的文件,假设其解压后的目录为:/data
基于 1.2 产生的 perf.data,后续步骤如下:
1、使用 perf script 工具对 perf.data 进行解析
perf script -i perf.data &> perf.unfold
2、将 perf.unfold 中的符号进行折叠:/data/stackcollapse-perf.pl perf.unfold &> perf.folded
3、最后生成 svg 图:/data/flamegraph.pl perf.folded > perf.svg
生成的火焰图如下:
关于火焰图的含义及分析网上有很多文章,这里不再赘述
Gprof
2.1 简介
gprof 用于监控程序中每个方法的执行时间和被调用次数,方便找出程序中最耗时的函数。在程序正常退出后,会生成 gmon.out 文件,解析这个文件,可以生成一个可视化的报告
2.2 使用方法
使用 gprof,需要在编译时,加入-pg 选项
另外只有在程序正常退出后才会生成 gmon.out,kill 进程的方法是没法生成 gmon.out 的。对于那些线程会一直 run 的服务,需要修改代码,让程序在某个时间点停止。
重新编译后,正常启动程序即可;然后在程序运行结束后,会生成 gmon.out 文件
使用如下命令,生成报名文件(其中 run 是二进制的名字):
gprof -b run gmon.out >>report.txt
report.txt 打开如下图所示:
2.3 图形化方法
gprof 的结果文件需要借助 gprof2dot.py 和 graphviz 来展示
使用 gprof2dot.py 生成 dot 文件
python gprof2dot.py report.txt >report.dot
需要说明的是,这里要求服务器已经安装了 python,并且要求 gprof2dot.py 与安装的 python 版本匹配。这两者是否匹配是一个需要运气、并且解决起来很无聊的事情,我的服务器上安装的 python 是 2.6.6,第一次从网上下载的 gprof2dot-2017.9.19 与 python 版本就不匹配,执行会出错。目前使用的版本与 2.6.6 是兼容的,如果需要可以与我联系。
dot 的打开需要 graphviz 工具,我是在 windows 下安装的 graphviz,这个工具下载很简单。下载后使用 gvedit.ext 打开前一个步骤产生的 report.dot 文件即可
这个图显的有些萌萌哒,这是因为我们的程序写的比较简单,对于一般的业务而言,这个图会比较复杂。
Valgrind
3.1 简介
valgrind 不是 linux 的原生工具,需要自行安装。valgrind 自身包含了多个工具:
Memcheck:用于内存泄漏检查
Callgrind:用于性能分析,会收集程序运行时间和调用关系
以及 Cachegrind、Helgrind 等
这里我们主要使用的 Callgrind 工具
3.2 使用方法
首先需要安装valgrind
解压安装包后,顺次执行:./configue 、make、make install 就可以了
使用 valgrind 来分析性能,必须使用 valgrind 来启动程序:
valgrind --tool=callgrind --separate-threads=yes ./run
–separate-threads 是指是否按线程来分别统计,如果不加,会将所有线程的结果打到一个文件里;否则会按线程分别打印到不同文件里。
程序执行结束后,会生成形如:callgrind.out.4263-01 的文件。这个文件直接分析起来有些困难,必须借助图形化的方式来浏览
3.3 图形化方法
valgrind 的图形化需要借助 kcachegrind.exe,大家可以自行下载,下载后在 windows 运行即可。这是打开 callgrind.out.4263-01 的结果:
工具比较
对于我们的需求:定位执行时间最长、占用 CPU 最多的函数 来说,这三个工具都可以达到目的。但这三者之间还是有一定的差距:
4.1 启动方式
Perf 虽然可以挂接进程但需要 root 权限。在普通权限下,Perf 和 Valgrind 必须使用前缀启动的方式来启动程序,这在某种程度上会影响到程序的性能。我们在压测的过程中发现使用 Valgrind 启动的时候,可以支持的在线总人数比直接运行程序要少很多。
4.2 程序侵入
Perf 和 Valgrind 都不需要修改 Makefile 或者程序,但 gprof 需要重新编译文件,并且对于线程一直 run 的服务,还需要修改代码让其自然退出,这在一定程序上侵入了程序。但从对性能影响上来看,gprof 可以最大限制的保留原程序的性能
4.3 结果展示
gprof 的结果是一颗倒树,这颗树展示了从根到叶子的所有结点的时间消耗;perf 的是一个金字塔,与 gprof 有异曲同工之妙;Valgrind 的结果是一条单路,指出的是某条调用路径上的时间消耗,并不是一个全局的展示。
4.4 监控原理
这是一个很专业的话题,目前对三者的监控原理还没有摸的太透,所以这里暂时空着。大家有兴趣可以先行研究。
本文转载自公众号云加社区(ID:QcloudCommunity)。
原文链接:
https://mp.weixin.qq.com/s/gKE8AbuqCLG0RwFVdWZS8Q
评论