gperftools 简单使用说明

简单使用说明

官方文档在这里

对 CPU 性能评测的步骤:

  • 编译程序时加入 profiler 动态链接库

    可以在构建系统中添加 profiler 动态链接库依赖,也可以在执行的时候,使用 LD_PRELOAD 来加载该动态链接库

  • 通过环境变量 CPUPROFILE ,激活评测行为

    如果不介意侵入被评测的代码,可以添加 "gperftools/profiler.h" 头文件,在被测代码开始前,调用 ProfilerStart("result.prof") ,结束的位置调用 ProfilerStop()

    环境变量 CPUPROFILESIGNAL 可以设置信号值,用于开启(第一次发信号)和终止(第二次发信号)性能评测。

    环境变量 CPUPROFILE_FREQUENCY 可以设置每秒采样次数。默认采样频率是每秒 100 次。

  • 通过 pprof 处理评测结果数据,生成可视化 pdf

    pprof --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