简介
gperftools是谷歌的一套开源性能测试工具,可以测试内存泄露和cpu性能。相对于linux自带的perf,gperf更加友好易用。
网址:https://github.com/gperftools/gperftools
使用
tcmalloc
作为线程池
tcmalloc提供了一个线程安全的内存池,可以链接到c++程序中,直接使用。它自动代替glibc的malloc,free,new,delete。
使用方法有两种:
- 直接链接
g++ test.cc -ltcmallo
- 通过设置 LD_PRELOAD 环境变量来使用
LD_PRELOAD=/usr/local/lib/libtcmalloc.so ./a.out
检测内存泄露
通过设置环境变量 HEAPCHECK,该变量支持三个值:normal (equivalent to "1"), strict, draconian
比如:
#include <iostream>
int main() {
int* p = new int[20];
return 0;
}
编译运行:
g++ test.cc -g // 增加-g选项,可以看到内存泄露出现在哪一行
HEAPCHECK=normal LD_PRELOAD=/usr/local/lib/libtcmalloc.so ./a.out
程序输出为:
WARNING: Perftools heap leak checker is active -- Performance may suffer
Have memory regions w/o callers: might report false leaks
Leak check _main_ detected leaks of 80 bytes in 1 objects
The 1 largest leaks:
*** WARNING: Cannot convert addresses to symbols in output below.
*** Reason: Cannot find 'pprof' (is PPROF_PATH set correctly?)
*** If you cannot fix this, try running pprof directly.
Leak of 80 bytes in 1 objects allocated from:
@ 556176d0f79c
@ 7fe7b39a2b97
@ 556176d0f6aa
If the preceding stack traces are not enough to find the leaks, try running THIS shell command:
pprof ./a.out "/tmp/a.out.11414._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --gv
If you are still puzzled about why the leaks are there, try rerunning this program with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with HEAP_CHECK_MAX_POINTER_OFFSET=-1
If the leak report occurs in a small fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB or with TCMALLOC_RECLAIM_MEMORY=false, it might help find leaks more repeatab
Exiting with error code (instead of crashing) because of whole-program memory leaks
可以看到,程序给出了详细的解释,并给出一个shell命令,可以使用gv命令以图形的方式详细显示出,内存泄露出现在哪一行,当然,需要编译的时候,打开debug选项
我们运行给出的shell命令pprof ./a.out "/tmp/a.out.11414._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --gv
cpu profiler
profile的原理是在程序运行的时候,以10ms为一个周期,对程序的堆栈进行采样,得到每个函数的运行次数
我们需要在运行程序的时候,指定生成的 prof 文件,并通过 LD_PRELOAD 加载 libprofiler.so 动态库
比如,运行一个