用TCMalloc监测程序内存使用情况

TCMalloc是一个比glibc2.3的malloc更快的内存管理库,通常ptmalloc2能在300纳秒执行一个malloc/free对,而TCMalloc能在50纳秒内执行一个分配对。
TCMalloc以能减少多线程程序之间的锁争用问题,在小对象上能达到零争用。
TCMalloc为每一个线程分配一个线程本地cache,少量的地址分配就直接从cache中分配,并且定期做垃圾回收,将线程本地cache中的空闲内存,返回给全局控制堆。
TCMalloc认为 size<=32K的为小对象,大对象直接从全局控制堆中以页(4K)为单位进行分配, 以就是说大对象总是页对齐的。
一个页能存入一些相同大小的小对象,实例中,一个页中存入了32个128bytes的小对象。
小对像的分配:将0-32K之间分为170个大小类别,当要申请内存时,舍入到一个合适的大小类别中。每一个线程有一个自己的内存使用链表,当分配一个小对象时,从中心内存中分配内存并加入到线程的本地内存链表中。
大对象的分配:大对象直接从中心内存堆中分配,以4K页为单位,并以连续的内存块分配 ,称为一个spens,一个spens包括连续的多个4K页.


使用:将libtcmalloc.so连接到程序中,或设置LD_PRELOAD=libtcmalloc.so
这样就可以用tcmalloc库中的函数替换系统的malloc, free, realloc, strdup内存管理函数。
环境变量:
TCMALLOC_DEBUG=<level> --调式级别取1-2
MALLOCSTATS=<level>  --设置显示内存使用状态的级别取1-2
自动内存泄漏检查:
TCMalloc库还能进行内存泄漏的检查,使用这个功能有两种方式,
1.将tcmalloc库连接到自己程序中,应该将tcmalloc库最后连接到程序中。
2.设置LD_PRELOAD="libtcmalloc.so"HEAPCHECK=normal ,这样就不需要重新编译程序。
找开检查功能,有两种方式可以开关泄漏检查功能:
1.使用环境变量,这样将对整个程序进行检查,如下面,对ls进行检查
HEAPCHECK=normal  /bin/ls
2.在源代码中插入检查点的方式,这样可能控制只检查程序的某些部分
HeapProfileLeakChecker checker("foo"); //开始检查
    Foo(); //要检查的部分
    assert(checker.NoLeaks()); //结束检查
调用checker时,建立一个内存堆快照,在调用checker.NoLecks时,建立另一个快照,然后比较这两个快照,如果内存有增长或任意的变化,NoLecks返回false,并输入一个信息告诉你,怎么样用pprof工具来分析具体的内存泄漏。(源代码中有更多的信息)
执行内存检查:LD_PRELOAD=libtcmalloc.so HEAPCHECK=strict HEAPPROFILE=memtm ./a.out
   执行完成后,会输入检查结果,如果有泄漏,pprof会输出泄漏了多少字节,是多少次分配的,并会输出详细的列表指出是在什么地方分配的,分配了多少次:
分配次数  百分比                             泄漏代码行
1000       90.8%    90.8%     1000  90.8% subfun tm.cpp:33
 101       9.2%    100.0%      101   9.2% obj::obj tm.cpp:15


比较两个快照:pprof --base=profile.0001.heap 程序名 profile.0020.heap


文本输出方式:
255.6  24.7%  24.7%    255.6  24.7% GFS_MasterChunk::AddServer
列:1 - 当前对象内部使用的内存数
列:4 - 当前对象内部使用的内存及它调用的其它对象使用的内存总数
列:2,5 - 分别表示第1列和4列所用的百分比
列:3 - 为第二列的累计和


3.有时一些内存泄漏是已知的,在这些地方我们可能关闭检:
#include ... 
void *mark = HeapLeakChecker::GetDisableChecksStart();
    <leaky code>           //不做泄漏检查的部分
    HeapLeakChecker::DisableChecksToHereFrom(mark);
注:有些libc中的例程可能要关闭检查才能正常工作。
环境变量:
HEAPPROFILE=<pre> -- 指定内存泄漏检查的数据导出文件
HEAPCHECK=<type>  -- 堆检查类型normal,strict,draconian


注:
好象不能检测出如下的内存泄漏
char *ch = new char[1000]; delete ch;   //只释放了第一个指针的情况

你可能感兴趣的:(多线程,工作,cache,delete,工具)