c/c++常用性能分析工具
GProf
缺点:
- 采样数据非常不准确:只能分析应用程序在运行过程中所消耗的用户时间,无法得到程序内核空间的运行时间
- 对多线程支持差
- 对release版本支持差
- 需要重新编译代码
Perf
优点:
- GNU自带,无需配置
- 可以不重新编译代码
缺点:
- 对使用锁较多的多线程应用程序支持差
- 对release版本支持差
PProf
优点:
- 采样结果相对最准确
- 对多线程支持好
- 可以指定需要分析的代码片段
- 对release版本支持好
- 使用灵活,官方文档详细
- 可以不重新编译代码
手动插桩采样
对于c/c++服务端应用,可以在代码中通过gettimeofday()函数插桩,计算各个桩之间的耗时,将耗时通过日志输出到文件,然后统计各个桩之间的耗时,分析应用程序性能瓶颈。
缺点:
- 需要预先插桩
- 需要重新编译代码
优点:
- 对release版本支持好
- 采样结果准确
- 对多线程支持好
- 可以对在线上运行的服务端应用程序进行性能监控
pprof的安装与配置
安装libunwind、gperftools
下载源码,从源码编译安装libunwind-1.6.0、gperftools-2.9.1。
sudo ./configure
sudo make -j
sudo make intall
默认安装不需要指定安装路径,安装完成后,/usr/local/include/下会新增对应头文件,/usr/local/lib/下新增动
态链接库文件。
安装后,可能需要更新动态链接库搜索路径:
sudo echo “/usr/local/lib” >> /etc/ld.so.conf
sudo ldconfig
安装graphviz
pprof绘制函数调用关系图,需要使用graphviz。
sudo yum install graphviz
sudo yum install ghostscript
安装后可以dot -v验证是否成功安装。
如何使用pprof分析mysql数据库性能及内核函数调用关系
指定需要分析的代码
#include <gperftools/profiler.h>
......
ProfilerStart(“file_to_save_sample_data.prof”);
// 需要分析的代码开始
......
// 需要分析的代码结束
ProfilerStop();
这个ProfilerStart()和ProfilerStop(),不是用来指定代码片段物理开始结束位置,而是逻辑开始、结束位置,所以ProfilerStop最好放在mysql退出过程调用的函数中,ProfilerStart()最好放在mysql启动过程调用的函数中。另外还有一种通过kill发送信号指定开始、结束时机的方式,这种方式不需要指定需要分析的代码,但是在mysql上没有试验成功。对于运行一段时间会自动退出的应用程序,还可以通过在启动命令中设置环境变量的方式开启pprof分析,但是一般服务端应用都不会自动退出。
编译链接
已在MySQL的CMake文件中增加链接pprof的开关,通过编译选项指定链接pprof的动态链接库即可:
cmake … -DWITH_DEBUG=0 -DWITH_PPROF=1 -DWITH_BOOST=/home/xxx/mysql-5.7.32/boost/ && make -j
如果编译结束没有报错,再查看一下是否连接了pprof的动态链接库:
ldd sql/mysqld
如果有指向/usr/local/lib/libprofiler.so2的依赖,则编译链接成功。
进行测试
可以进行sysbench压力测试或其它测试,测试结束后,正常结束进程:不能用kill -9杀进程,推荐kill pid。测试过程中生成的数据会保存到指定的data目录下。
生成测试结果
生成函数耗时分析结果:
pprof --text ./build/sql/mysqld file_to_save_sample_data.prof > file_to_save_result.txt
生成函数耗时及调用关系图:
pprof --pdf ./build/sql/mysqld file_to_save_sample_data.prof > file_to_save_result.pdf
节点和边剪枝阈值控制:
使用–nodefraction和–edgefraction参数可以控制生成pdf图的剪枝阈值。