tcmalloc的memory heap profiler
在写C++程序时,有时候会出现内存问题,例如当程序的负荷升高时,内存占用不断升高,但是,当程序的负荷下降时,内存占用也没有降低,这种情况对于标准的malloc内存分配,很有可能是内存泄漏,而对于tcmalloc来说,也可能只是内存没有被放回系统分配器。对于tcmalloc的内存分配机制,可以参考
https://gperftools.github.io/gperftools/tcmalloc.html
如果想比较准确的判断这种情况,可以使用malloc_extension.h中的MallocExtension::instance()->GetStats(),如果发现随着应用负载变高,同时Application占用变高,但是随着负荷降下来,很大的一部分Application占用变成了free占用。例如当qps为1000次/s升到10000次/s,Application占用由50M上升到450M,但是当qps降低到1000次/s时,Application占用又回到了50M的话, 虽然top中的内存占用和qps为10000次/s的时候基本一样,还是基本可以确定没有内存泄漏。如果Application占用明显高于50M,而分析代码逻辑,不应该出现这种情况时,就有可能是存在内存泄漏了。这时候,需要考虑使用gpertfools heap profiler。
实现gperftools heap profiler时,可以使用-Bdynamic的方式使用libtcmalloc.so动态库。使用这个动态库时,并不一定会启用heap profiler,你需要指定参数,具体可以参考
https://gperftools.github.io/gperftools/heapprofile.html
当发现你所指定的目录有xxx.heap文件生成时,说明已经启用了heap profiler。当前,使用heap profiler的时候,存在一个比较严重的问题,就是cpu占用很高,基本达到原先的十倍以上,导致很多heap profiler很难正常进行,因为负荷发生改变,行为就可能发生改变。而使用上面的打印方式,基本不会改变负荷,在这方面,使用打印的方式优势很大。之前查询相关文档,有一个是这样说的:
https://github.com/gperftools/gperftools/issues/330
但是,实际采用来看,效果不是很明显,如果各位在使用的时候,有好的解决这个的办法,希望能够告诉我。
对于生成的heap文件,可以使用如下方法使用:
pprof --text ./xxx.exe /tmp/profile.0100.heap
pprof --text --base=/tmp/profile.0004.heap ./xxx.exe /tmp/profile.0100.heap (两个heap文件的内存占用差别)
其中的--text指定展示的格式,--text是文本展示,还有很多别的展示方式,例如:
--text Generate text report
--stacks Generate stack traces similar to the heap profiler (requires --text)
--callgrind Generate callgrind format to stdout
--gv Generate Postscript and display
--evince Generate PDF and display
--web Generate SVG and display
--list=<regexp> Generate source listing of matching routines
--disasm=<regexp> Generate disassembly of matching routines
--symbols Print demangled symbol names found at given addresses
--dot Generate DOT file to stdout
--ps Generate Postscript to stdout
--pdf Generate PDF to stdout
--svg Generate SVG to stdout
--gif Generate GIF to stdout
--raw Generate symbolized pprof data (useful with remote fetch)
--collapsed Generate collapsed stacks for building flame graphs
(see http://www.brendangregg.com/flamegraphs.html)
如果方便的话,尽量使用gv, web等类似于图片的展示格式,因为很多格式可以显示调用的顺序,以及每个调用所占的内存,对于分析来说,更加友好。如果这是台远程的服务器的话,可以先生成dot格式,dot格式,是graphviz使用的一种文件格式。
然后通过一下办法:
转为png图片
dot -Tpng xxx.dot -o xxx.png
转为pdf文件
dot -Tpdf xxx.dot -o xxx.pdf
然后,例如通过python3来实现一个简单的http server,例如python3 -m http.server 12000,再通过网页打开这个静态的文件服务器页面,http://xxx.xxx.xxx.xxx:12000/xxx.png来获取这个文件,进行分析。gperftools的memory profiler的使用,不是那么容易掌握,需要使用多次才能比较熟练,而且还有cpu占用太高的问题,导致有些情况下,使用memory profiler,表现就会有所差别,很明显的一个差别就是,一个之前需要10min就可以发现明显的内存增加,现在可能需要一两个小时,这些都会对使用memory profiler产生很大的不利影响,所以最重要的还是认真写程序,不要随便出现内存泄漏的问题。