如何配置Valgrind按需收集数据以排查延迟触发的内存泄漏问题
解决方案
方案1:基于Massif原生能力实现按需收集
Massif本身支持启动时禁用收集,等到需要时再触发日志记录,全程几乎不会影响程序前期的运行性能:
- 启动Valgrind时添加
--start-disabled=yes参数,命令参考:
启用该参数时Valgrind仅做最小程度的插桩,性能损耗不到5%,程序基本等同于全速运行。valgrind --tool=massif --massif-out-file=massif.out.%p --start-disabled=yes 你的应用启动命令 - 在你的项目代码中引入Massif客户端头文件:
#include <valgrind/massif.h>,同时注册信号处理逻辑,比如收到SIGUSR1信号时开启快照收集,收到SIGUSR2信号时停止收集并导出快照,对应调用的接口分别是VALGRIND_MASSIF_START_SNAPSHOTS、VALGRIND_MASSIF_STOP_SNAPSHOTS、VALGRIND_MASSIF_DUMP_SNAPSHOTS。 - 等程序运行到接近泄漏触发的时间点,执行
kill -SIGUSR1 <应用进程PID>即可启动收集,收集到足够数据后执行kill -SIGUSR2 <应用进程PID>导出日志,后续直接分析生成的massif输出文件即可定位泄漏点。
如果不方便修改业务代码,也可以用动态插桩工具注入上述Massif控制逻辑,只是实现复杂度略高于修改代码。
方案2:用低开销工具gperftools替代Massif排查
如果不想修改代码也不想引入Valgrind的额外开销,可以选择性能损耗仅2%~3%的gperftools heap profiler,完全不会影响泄漏复现的条件:
- 安装gperftools后,启动程序时预加载tcmalloc即可开启堆分析能力,命令参考:
LD_PRELOAD=/usr/lib/libtcmalloc.so HEAPPROFILE=heap_profile.out ./你的应用启动命令 - 程序运行到接近泄漏触发时间点时,执行
kill -SIGUSR1 <应用进程PID>即可触发堆快照导出,多轮导出的快照可以用pprof工具对比差异,直接定位持续增长的内存分配链路,精度和Massif相当。
内容的提问来源于stack exchange,提问作者Lukasz Kamisinski
相关产品推荐
相关产品推荐

