gperftools使用

来源:互联网 发布:程序员杂志 2016 pdf 编辑:程序博客网 时间:2024/06/06 00:42

近期尝试使用gperftools对C++内存泄露进行排查,所以对gperftools进行了一些了解。gperftools是google用来进行程序性能优化的工具集合,主要包括tcmalloc和profiler两个库。其可以提供如下的功能:

  1. tcmalloc:与glibc中的malloc函数相比,tcmalloc的内存分配效率要远高于malloc,可以提高高并发的性能 ,降低系统的负载
  2. cpu profiler:对程序中各个函数使用的CPU情况进行监控探测
  3. heap checker:对程序是否发生内存泄露进行检测
  4. heap profiler:对程序中申请的内存区域进行监控

heap checker

使用

对于使用heap checker的使用,需要注意的是一般是对整个程序进行检测,要求这个程序会自动退出,而不是那种会不停的运行的服务。其实gperftools的官方文档中说当发现内存泄露的同时会通过exit()使程序退出并打印相关的内存信息。

In this case, the heap-checker starts tracking memory allocations before the start of main(), and checks again at program-exit. If it finds any memory leaks – that is, any memory not pointed to by objects that are still “live” at program-exit – it aborts the program (via exit(1)) and prints a message describing how to track down the memory leak (using pprof).

对于heap checker的使用有两种方法:

  1. 设置LD_PRELOAD 来预加载tcmalloc库,然后执行相关的运行命令,例如:

        LD_PRELOAD=/usr/lib64/libtcmalloc.so    HEAPCHECK=normal ./example1
  2. 在编译时使用静态库进行连接,然后执行相关的运行命令,例如:

        g++ -g -o example1 example1.cpp -ltcmalloc    HEAPCHECK=normal ./example1

对于可以退出并且发生内存泄露的程序,其输出结果如下:

这里写图片描述

对于发生内存泄露但是一直不能够退出的程序,其输出结果如下:

这里写图片描述

检查模式

可以注意到对于第二行命令中前几个字段HEAPCHECK=normal,可以理解为设置进行内存检查时的检查类型(或者检查的严格程度)。一共有以下几种检查的方式:

  1. minimal:忽略在进入main()函数之前的所有内存分配
  2. normal:检查在程序运行时的所有内存分配的情况,报告在程序结束时没有释放的内存。在google中最常用的模式就是这种模式。
  3. strict:与normal类似,但是也报告在全局析构中忘记析构导致发生的内存泄露
  4. draconian:属于一种更精确的内存检查,如果申请的没存没有被释放,他就会报告内存泄露
  5. local:使用这个模式可以实现只检查程序中的指定部分的代码是否发生内存泄露。可以检测开始的地方创建 HeapLeakChecker对象,然后在检测结束的地方调用NoLeaks(),例如:

    HeapLeakChecker heap_checker("test_foo");  {    //code that exercises some foo functionality;    //this code should not leak memory;  }  if (!heap_checker.NoLeaks()) assert(NULL == "heap memory leak");
  6. as-is:利用这个模式再加上一些环境变量的设置,可以进行更灵活的检查

官方文档是这样写的:

“Minimal” heap-checking starts as late as possible in a
initialization, meaning you can leak some memory in your
initialization routines (that run before main(), say), and not trigger
a leak message. If you frequently (and purposefully) leak data in
one-time global initializers, “minimal” mode is useful for you.
Otherwise, you should avoid it for stricter modes.

“Normal” heap-checking tracks live objects and reports a leak for any
data that is not reachable via a live object when the program exits.

“Strict” heap-checking is much like “normal” but has a few extra
checks that memory isn’t lost in global destructors. In particular, if
you have a global variable that allocates memory during program
execution, and then “forgets” about the memory in the global
destructor (say, by setting the pointer to it to NULL) without freeing
it, that will prompt a leak message in “strict” mode, though not in
“normal” mode.

“Draconian” heap-checking is appropriate for those who like to be very
precise about their memory management, and want the heap-checker to
help them enforce it. In “draconian” mode, the heap-checker does not
do “live object” checking at all, so it reports a leak unless all
allocated memory is freed before program exit. (However, you can use
IgnoreObject() to re-enable liveness-checking on an object-by-object
basis.)

“Normal” mode, as the name implies, is the one used most often at
Google. It’s appropriate for everyday heap-checking use.

跳过某些代码的检查

既然前面已经提到了可以设置检查程序的部分代码,对于那些已经知道会放生内存泄露后者发生内存泄露但是可以接受的代码,同样也可以设置不进行检查,例如:

...   {     HeapLeakChecker::Disabler disabler;     <leaky code>   }...

除了上述的方法,还有一种方法就是使用IgnoreObject() 在此函数中传入需要忽略检测的对象的指针,可以使用UnIgnoreObject()取消这个忽略。

环境变量

  1. HEAP_PROFILE_ALLOCATION_INTERVAL:上文说每当一定量的内存被新申请分配出来时,就会输出profile文件,这个变量值就是控制多少字节,默认是(1024*1024*1024)1GB,粒度相对比较大,可以调整为几百MB甚至更小。
  2. HEAP_PROFILE_MMAP:有时候程序申请内存的方式是通过mmap,sbrk系统调用而不是malloc free,如果想profile这些内存,可以开启这个变量,默认是false。我们工程代码中就有些调用了mmap申请大块内存的地方,开启这个环境变量,能更准确跟踪内存走向。
  3. HEAP_PROFILE_MMAP_ONLY:如其名,只profile mmap,sbrk申请的内存。

heap profiler

heap profiler也是使用tcmalloc库,通过heap profiler可以不断的生成相应的profile文件。对于那些运行一段时间就会退出的程序,一般会生成一个XXXXX-end.heap的文件可以使用pprof命令以及相关的参数(–text或者–pdf)进行查看;但是,对于那些正常情况下的永远运行不会停止的服务,使用heap profiler可以根据生成的XXXX.heap文件跟踪程序的内存使用情况,也可以使用pprof命令进行查看。

使用

heap profiler的使用与heap checker的使用方法差不多,也是有两种方式:

  1. 设置LD_PRELOAD 来预加载tcmalloc库,然后执行相关的运行命令,例如:

    LD_PRELOAD=/usr/lib64/libtcmalloc.soHEAPPROFILE=/tmp/example1 ./example1
  2. 在编译时使用静态库进行连接,然后执行相关的运行命令,例如:

    g++ -g -o example1 example1.cpp -ltcmallocHEAPPROFILE=/tmp/example1 ./example1

其中HEAPPROFILE 环境变量是用来设置生成的dump文件的前缀的,其运行结果如下:

这里写图片描述

原创粉丝点击