zoukankan      html  css  js  c++  java
  • tcmalloc 内存分析

    “different,but not less. 不同,但也不差!”

    前记

    出现内存错误,查问题是一方面,更多的是需要考虑,以后写代码如何不出现内存错误。总结很关键。

    • 《Linux多线程服务端编程使用muduo网络库》这本书说的是RAII技术(后期研究下,做一些实践)。
    • 自己的总结:new 出的内存,不进行类之间的长途传递,若出现这种情况,需要思考下是否真的有必要如此。比如,自己看到的一种比较难受的管理方式:在调用中,new出一个对象A传递指针到另外一个对象B中,并且,最后在对象B析构函数中去释放了A。这种情况,我现在认为的解决办法是传递必要参数到对象B中去new,并且在对象B中的析构中去释放。便于管理。

    一、简介

    1. 最近在查程序的内存泄漏问题,是在tcmalloc内存分配的基础上,关于tcmalloc是介绍:主要参见两篇博文:
              (1) 官方文档介绍,主要介绍原理和为什么tcmalloc比glic的快:tcmalloc
              (2) 知乎之前看到一篇分析原理的,楼主添加了很多自己画的图分析,可以当做翻译看:图解tcmalloc
    1. google 出了一套gperftools工具 可以分析cpu占用(profiler.h),分析内存占用(heap-profiler.h),检查内存泄漏(heap-checker.h) ,这里主要讲后面两者的使用
    2. 内存检查的基本原理是:检查运行的代码每个函数中的内存使用情况,生产内存快照文件(即我们需要得到的分析原始数据),内存快速增长的情况下会生成很多的内存快照,后期分析可以前后对比看是什么堆栈的内存分配最多。

    二、程序环境配置

    1. tcmalloc环境和库  (http://github.com/gperftools/gperftools) 源码安装
    2. 生成 cpu/内存 采样数据的分析工具:
              (1)pprof工具使用需要安装  graphviz(http://www.graphviz.org)  和 ghostscript(www.ghostscript.com)
     

    三、内存分析方式

    1. 情况1:程序本身链接了tcmalloc库,在不重新编译的情况下,使用环境变量进行数据采集     

       #启动程序的方式:
       HEAPCHECK=normal   HEAPPROFILE=prefix  ./test      //需要前台启动程序
         #第一个参数HEAPCHECK表示检查的严格程度    HEAPPROFILE参数表示生产的内存快照
         #默认生成的内存快照文件在/tmp  目录下。

             2. 情况2:在程序中添加接口,以便后期线上直接调用分析

            
    使用HeapProFilerStart("prefix")  "prefix"是生成文件的前缀和 HeapProFilerStop 接口  
    1.在头文件 <gperftools/heap-profiler.h> 中。 2.可以使用http接口或者telnet 使用方式:程序可以前台,也可以后台,启动之后,发命令或者请求让其执行HeapProFilerStart ,
    然后复现程序内存上涨的情况,接着在程序的当前目录可以看到 prefix_heap.
    0001.heap (prefix为start传入的前缀),
    随着内存上涨,会持续的生很多的内存快照,差不多的时候stop。然后开始使用获得的内存快照分析。

           内存快照的分析方式:

    • 单个快照查看:  使用pprof生成pdf图
    执行命令: pprof --pdf  ./test  ./prefix_heap.0001.heap  > 1.pdf  
    • 对比前后快照查看方式:依然使用pprof生成pdf
    执行命令:pprof --pdf  --base=prefix_heap.0001.heap   ./test  ./prefix_heap.0002.heap  > 1.pdf 
          
          根据生成的pdf文件查看,主要关注百分比占比很高的堆栈,然后根据这个堆栈去程序中分析申请的内存是否都释放。
          对比生成的数据可以很明显看出内存上涨是哪些函数调用产生的,但是需要根据实际的代码去分析到底有没有内存没有释放。
           

         3.检查片段代码的内存泄漏  :以上两种方式只是用来获取程序内存分配情况的,接下来的方式可以直接检查某个函数的使用到底有没有内存泄漏

            (1)需要在代码中嵌入检查: 使用头文件<gperftools/heap-checker.h> 中的类 HeapLeakChecker 
            (2)添加的代码片段:
      
    HeapLeakChecker heap_checker("test_foo");
    {
        code that exercises some foo functionality;
        this code should preserve memory allocation state;
    }
    if (!heap_checker.SameHeap()) assert(NULL == "heap memory leak");
              (3)启动程序: HEAPCHECK=normal  ./test
              (4)输出:
    • 若没有内存泄漏: 
             
     No Leaks found for check "test_foo" 
    • 若存在内存泄漏:
    Leak check _main_ detected leaks of 1136 bytes in 2 objects The 2 largest leaks:
    Leak of 568 bytes in 1 objects allocated from:
    @ 7fa7f4197dd2
     
    If the preceding stack traces are not enough to find the leaks, try running THIS shell command:
     
    pprof ./bin/exe "/tmp/exe.7539._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --pdf
     
    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 mi Exiting with error code (instead of crashing) because of whole-program memory leaks
     
    以上就是内存泄漏的情况下的输出,这个输出不够详细,无法看出泄漏情况,可以参照他的建议执行pprof命令:
    pprof ./bin/exe "/tmp/exe.7539._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --pdf > 1.pdf
     
    查看pdf,同上分析内存分配堆栈来查找内存泄漏的问题。
     

  • 相关阅读:
    pandas Dataframe filter
    process xlsx with pandas
    data manipulate in excel with easyExcel class
    modify registry in user environment
    add number line in vim
    java import webservice
    ctypes MessageBoxA
    music 163 lyrics
    【python实例】自动贩卖机
    【python基础】sys模块(库)方法汇总
  • 原文地址:https://www.cnblogs.com/panhao/p/10166381.html
Copyright © 2011-2022 走看看