0 介绍

gperftools是Google开源的一款非常使用的性能分析工具集。

 主要包含五部分:

(1)TC malloc内存分析器

    Tcmalloc是Thread Cache malloc的缩写,号称比ptmalloc2更快的内存管理库。

    Tcmalloc原理是为每个线程单独分配一个线程本地的Cache,少量的地址分配就直接从Cache中分配,并且定期做垃圾回收,将线程本地Cache中的空闲内存返回给全局控制堆;Tcmalloc认为小于等于32K的对象是小对象,大对象直接从全局控制堆以页为单位进行分配,所以大对象总是页对齐的;Tcmalloc中一个页可以存入一些相同大小的小对象,小对象从本地内存链表中分配,大对象从中心内存堆分配。

    优势:

    1)快速:相比ptmalloc2,Tcmalloc的性能城北提升。尤其是Tcmalloc可以减少多线程之间锁的竞争问题,在小对象(32K)上能达到零竞争。

    2)占用空间小:相比ptmalloc2,tcmalloc对小对象占用空间进行了优化。例如:分配N个8字节对象只需要占用8N*1.01字节的空间。即,只需要多使用1%的空间。而ptmalloc2中每个对象都需要使用一个4字节的头信息,最后占用的字节可能达到8N*8。

    3)不易出现内存暴涨(ptmalloc2使用内存池,长时间没有将内存还给系统就会造成内存暴涨,tcmalloc可以通过MallocExtension::instance()->ReleaseFreeMemory()类设置内存还给系统的速度)。

(2)Heap-profiler

  Heap-profiler是内存监控器,可以随时知道内存的使用情况[2]。

(3)Heap-checker

  Heap-checker是专门检测内存泄漏的工具

(4)Cpu-profiler

 Cpu-profiler主要是通过采样的的方式,给出一段时间内程序实际占用cpu时间偏进行统计和分析。

(5)pprof

 pprof 是用于解析 profile 文件的 perl 脚本工具。

1 安装

1.1 安装 libunwind

下载源码,这里下载的1.6.2

wget http://mirror.rabisu.com/savannah-nongnu/libunwind/libunwind-1.6.2.tar.gz
tar -zxv -f libunwind-1.6.2.tar.gz
cd libunwind-1.6.2
./configure 
make
sudo make install

1.2 安装 gperftools

下载源码:https://github.com/gperftools/gperftools/releases/download/gperftools-2.9.1/gperftools-2.9.1.tar.gz

tar -zxv -f gperftools-2.9.1.tar.gz
cd gperftools-2.9.1
./configure
make
sudo make install

 1.3 更新动态库

sudo ldconfig

 1.4 安装成功 pprof -v

2 内存泄露检测

2.1 源码memory_leak.cpp

#include <iostream>

int func() {
    int *p = new int(10);
    return 0;
}

int main() {
    std::cout << "memory leak test" << std::endl;
    return func();
}

2.2 编译

g++ -g memory_leak.cpp -o leak -ltcmalloc

注意:这里可能会出现找不到tcmalloc库,原因可能是没有用 ldconfig  更新动态库文件,该命令使用指南

如果是大工程,官方给出了两种方法进行链接tcmalloc库:

方法一:编译进工程,在makefile文件中编译进tcmalloc库,运行如下命令

HEAPCHECK=normal ./main

方法二:不编译进工程,只需要在运行时通过LD_PRELOAD命令加载tcmalloc库

// pprof 在环境变量中就不用写
env LD_PRELOAD="/...路径.../lib/libtcmalloc.so" PPROF_PATH=/...路径.../bin/pprof HEAPCHECK=normal ./main

注意:官方推荐第一种,第二种说不安全

2.3 运行代码

HEAPCHECK=normal ./leak

完整程序运行 的 heap checker 支持 4 种模式:

  • minimal:在程序初始化期间(即 main 函数运行前)不进行内存泄露检查
  • normal:正常模式,通过跟踪某块内存是否可以被 live object 来访问,来判断是否出现内存泄露
  • strict:类似于 normal 模式,但是对全局对象的内存泄露有一些额外的检查
  • draconian:在该模式下,只有所有申请的内存都被释放,才认为没有出现内存泄露

一般使用 normal 模式就可以满足日常要求了。

出现结果:

 Leak of 10 bytes in 1 objects allocated from: // 表示有10字节的内存被泄露,但不知到什么位置,根据提示运行:

有图像界面:

pprof ./leak "/tmp/leak.442._main_-end.heap" --inuse_objects --lines --heapcheck  --edgefraction=1e-10 --nodefraction=1e-10 --gv

我这里没装,将--gv去掉:

pprof ./leak "/tmp/leak.442._main_-end.heap" --inuse_objects --lines --heapcheck  --edgefraction=1e-10 --nodefraction=1e-10

然后输入top即可出现位置(可以输入help,查看命令帮助):

 注意:这个工具好像只有在程序正常退出时才能检测的比较完全!

参考资料:

(1)gperftools的Heap Checker_gperftools 内存泄漏_wangwangblog的博客-CSDN博客

(2)使用 gperftools 检测内存泄露_线上幽灵的博客-CSDN博客

(3)linux程序莫名异常怎么查 - 风纳云

(4)gperftools工具检测内存泄露 - 爱码网

(5)使用 gperftools 进行 C++ 代码性能分析 - 知乎

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐