gperftools 简单使用说明
简单使用说明
官方文档在这里。
对 CPU 性能评测的步骤:
编译程序时加入 profiler 动态链接库
可以在构建系统中添加 profiler 动态链接库依赖,也可以在执行的时候,使用
LD_PRELOAD
来加载该动态链接库通过环境变量
CPUPROFILE
,激活评测行为如果不介意侵入被评测的代码,可以添加
"gperftools/profiler.h"
头文件,在被测代码开始前,调用ProfilerStart("result.prof")
,结束的位置调用ProfilerStop()
。环境变量
CPUPROFILESIGNAL
可以设置信号值,用于开启(第一次发信号)和终止(第二次发信号)性能评测。环境变量
CPUPROFILE_FREQUENCY
可以设置每秒采样次数。默认采样频率是每秒 100 次。通过
pprof
处理评测结果数据,生成可视化 pdfpprof --pdf ./program result.prof > result.pdf
关于内存等评测类似,只是动态链接库换成 tcmalloc
, 环境变量换成 HEAPPROFILE
。
编译自己的代码
example.cpp
并链接tcmalloc
动态链接库g++ -g -o example example.cpp -ltcmalloc
设置环境变量
HEAPPROFILE
运行编译出来的可执行程序HEAPPROFILE=text ./example
运行完成后,会生成一个结果文件
test.0001.heap
。获得可视化结果:
pprof --pdf ./example test.0001.heap > test.pdf
疑难问题
如果可执行程序的代码里,不调用任何 profiler 里的函数,在 Linux 下链接时,无法将 libprofiler 链接到可执行程序里(编译、链接成功,但是 ldd 发现没有 libprofiler); MacOS 下看起来没有问题。猜测是两个平台链接器不同(一个是 llvm ld,一个是 gnu ld)导致的,似乎是 gnu ld 做了优化,去掉了没有被使用的动态库链接。
通过 ChatGPT,找到答案,可以加入 "-Wl,–no-as-needed" 参数给链接器。但是 clang++ 的链接器不识别该参数,所以需要在 CMakeLists.txt 中判断一下链接器。
ChatGPT 首先给出如下解决方案:
if(CMAKE_LINKER_IS_GNU) # GNU ld linker target_link_libraries(your_executable_name -lprofiler) else() # Other linker target_link_libraries(your_executable_name profiler) endif()
在 Linux 下测试竟然不生效,搜索了一下 CMAKE_LINKER_IS_GNU
, 看起来像是 ChatGPT 胡诌的。继续问 ChatGPT,得到如下代码:
if(CMAKE_LINKER_IS_GNU OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${ARG_NAME} PRIVATE -Wl,--no-as-needed ${PROFILER_LIBRARIES}) else() target_link_libraries(${ARG_NAME} PRIVATE ${PROFILER_LIBRARIES}) endif()
References
- https://gperftools.github.io/gperftools/
- https://gernotklingler.com/blog/gprof-valgrind-gperftools-evaluation-tools-application-level-cpu-profiling-linux/
- https://www.sobyte.net/post/2022-04/gperftools/
- http://euccas.github.io/blog/20170827/cpu-profiling-tools-on-linux.html
- https://www.redhat.com/architect/perf-vs-gprofng