本文将要学习如何使用gperftools工具定位C/C++程序的性能瓶颈,并用kcachegrind工具进行可视化展示。
gperftools简介
gperftools(Google Performance Tools)是由谷歌开源的性能分析工具,能够对程序进行profile,通俗的讲就是能够以一定的频率对程序的堆栈进行采样,采样的次数越高,说明这个堆栈对应的代码越热。这个功能对于定位性能瓶颈十分有用。
本文选用gperftools的原因有几点:
(1)非侵入性,也就是不用改应用代码;
(2)对应用性能影响相对小,对比valgrind等工具;
(3)支持分析多线程程序。
注:此工具的安装和详细信息请参考官方网站。
示例代码
#include <iostream>
using namespace std;
void func2()
{
static int i = 0;
++i;
}
void func3()
{
static int i = 0;
++i;
}
void func1()
{
for (;;) {
for (int j = 0; j < 3; ++j) {
func2();
}
func3();
}
}
int main()
{
func1();
return 0;
}
操作系统:Linux
g++版本:9.3.1
编译命令: g++ test.cpp -o test -g
代码分析:以上代码中main函数调用func1函数,在func1函数中无限循环调用func2和func3函数。
热点定位
步骤一:运行示例程序,以LD_PRELOAD gperftools动态库的方式
[root@fedora-36 test]# LD_PRELOAD="/usr/local/lib/libprofiler.so" CPUPROFILE=prof.out CPUPROFILESIGNAL=12 CPUPROFILE_FREQUENCY=10000 ./test 2>&1 > /dev/null
Using signal 12 as cpu profiling switch
其中,各项参数的解释如下,您可根据自己实际情况进行设置:
(1)可执行程序名:test
(2)gperftools动态库:/usr/local/lib/libprofiler.so
(3)采样输出的文件名:prof.out
(4)控制采样开始、结束的Linux信号:12
(5)采样频率:10000次/秒
步骤二:开始采样
使用向被采样程序发送linux信号的方式。若应用程序已经将Linux信号截获,则无法采样,需要修改应用程序不截获Linux信号。
命令:kill -12 PID
注:PID是被采样的程序的进程id,需要用实际的pid进行替换。
步骤三:结束采样
大约等待10秒左右,再次向被采样程序发送linux信号12,以结束采样。
命令:kill -12 PID
此时,查看当前目录,会发现生成了一个名为prof.out.0的文件
步骤四:生成可视化的采样文件
命令1:pprof test prof.out.0
格式:pprof 被采样的可执行程序名 生成的采样文件名
注:pprof程序是gperftools自带的程序
命令2:callgrind callgrind.out
注:生成callgrind文件,用来使用kcachegrind工具进行可视化展示
步骤五:使用kcachegrind工具展示采样结果
kcachegind工具支持Windows和Linux操作系统。操作较简单,只需要将步骤四中生成的callgrind.out文件导入工具中即可。下图为采样结果在kcachegrind软件中的可视化展示。
一、导入采样文件至kcachegrind软件
二、查看代码热点信息
从上图可以看出函数的调用关系,main函数调用func1,func1调用func2和func3。其中,func1中较大的热点如下:
(1)第16行的for循环,占用了49.74%,占比最高;
(2)第17行的func2函数,占用了31.59%。
结束语
通过本文的学习,我们掌握了如何对C/C++程序进行profile,能够帮助我们细粒度地分析程序热点。建议读者实际操作一下,掌握这项技能。