分析tcmalloc 内存增长 —- pprof

有时候程序莫名内存上涨厉害,但不是泄漏,如何定位哪申请使用的大量内存呢?

如果没使用tcmalloc,使用heaptrack工具(git clone https://github.com/KDE/heaptrack.git);

如果使用了tcmalloc,可以通过tcmalloc自带的工具来分析

一 工具

  1. tcmalloc
  2. pprof

pprof相当于分析器,阅读器,分析阅读的内容为heap文件,内容包括

  • 每个活跃分配的大小
  • 分配的调用栈
  • 分配次数

二 生成heap文件

  • 手动
    在程序的入口或需要开始分析的地方,添加 HeapProfilerStart(“文件路径”)。
    在程序结束或需要停止分析的地方,添加 HeapProfilerStop()。
    在需要手动生成快照的地方,添加 HeapProfilerDump(“文件名”)。

  • 自动
    设置环境变量,动态加载设置环境变量即可,tcmalloc库加载时会读取并解析这个环境变量,从而开启堆分析功能

    1
    export HEAP_PROFILE=/tmp/myapp_heap

    如果是静态加载,需代码中启动:HeapProfilerStart

  • 补充说明
    自动生成文件的时机:申请内存超过阈值时会自动生成,阈值可以通过HEAP_PROFILE_ALLOCATION_INTERVAL环境变量来设置

三 分析heap文件(快照)

单次快照

1
2
3
4
5
# 文本格式
pprof test_heap --text /tmp/test_heap.0001.heap

# 火焰图
pprof --svg /path/to/my_program.hprof > flamegraph.svg

两次快照:

1
2
3
4
5
# 对比两次快照
pprof --inuse_space --base=/tmp/my_app.0001.heap /tmp/my_app.0002.heap

# 生成火焰图
pprof --svg --inuse_space --base=/tmp/my_app.0001.heap /tmp/my_app.0002.heap > diff_flamegraph.svg

火焰图需要额外安装

1
yum install graphviz

sample

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <gperftools/heap-profiler.h>
#include <cstdlib>
#include <iostream>

int main() {
HeapProfilerStart("/tmp/test_heap");
void* p = malloc(16 * 1024 * 1024); // 分配 16MB
std::cout << "Allocated 16MB\n";
HeapProfilerDump("after_alloc");
free(p);
HeapProfilerStop();
return 0;
}
1
g++ test_heap.cc -ltcmalloc -lpthread -lunwind -o test_heap