C++使Valgrind和gperftools解决内存问题

近年,在对于系进行性能测试,暴露一些题目。在定位过程中品尝使用一些家伙,有效之增援识别问题,并且解决了问题。由于问题比较独立,分享给大家,以便大家遇到类似题材经常,借鉴参考。

工具介绍


1 Valgrind

Valgrind是千篇一律仿照Linux下,开放源代码(GPL
V2)的仿真调试工具的联谊。Valgrind由本(core)以及因内核的外调试工具组成。内核类似于一个框架(framework),它套了一个CPU环境,并提供劳务为任何工具;而其他工具则接近于插件
(plug-in),利用内核提供的劳务到位各种特定的内存调试任务。

valgrind的结构图

内:Memcheck。这是valgrind应用最常见的家伙,一个重量级的内存检查器,能够发现出中多数内存不当使用状况,比如:使用非初始化的内存,使用都刑满释放了底内存,内存访问越界顶

2. Heap Checker

google-perftools 是平慢性对 C/C++ 程序的特性分析工具,它是一个守 BSD
协议的开源项目。提供四个器:包括tcmalloc,heap-profiler,
heap-checker,CPU
profiler。heap-checker专门检测内存泄漏,heap-profiler则是外存监控器,可以随时了解当前内存以情况(程序中内存以热点),当然为能够检测内存泄漏。

3. getrusage

linux提供rusage结构,可以描述业务经过内存以状态,类似ps aux。

用工具定位解决内存问题


老三独独立问题,处理过程如下:

1. new expression导致的内存泄漏

1.1 问题讲述

从今性质测试时,统计主机可用内存减少,明显是内存泄漏。

祈求2-1 12分钟主机内存变化情况

1.2 问题定义分析

每当性测试主机安装Valgrind来拓展内存泄漏分析。利用Valgrind启动程序:

valgrind –tool=memcheck –leak-check=full –show-leak-kinds=all
–trace-children=yes ZSmartOCPro IN 2>&1| tee ZSmartOCPro_IN.txt

出殡业务信息,然后退出工作过程,可以变分析文件。

希冀2-2 三独事情包内存统计摘要

图2-3 九单业务包内存统计摘要

希冀2-4 可能性能泄露点

从今对比数据看,肯定在内存泄漏。在作业代码中,为了提高性能,设计及采取new
expression(参考:http://en.cppreference.com/w/cpp/language/new)内存模式,即将以内存管理起来,重复使用,减少频繁申请内存,从而加强性能。

图2-5 new expression

DataNode管理之多少与夫本人还是运这种方法。理论上次内存不在释放,也不该发泄露。从剖析日志来拘禁,因为DataNode中有map和vector中内存没有失败。map和vector的外有着stl自行管理,在DataNode对应的Clear函数,增加map和vector的clear调用,来刑释解教内存。测试时发现,这样的修改并没有因此,why?
map和vector的内存模式也是new
expression模式,clear只是理清计数器,并没有减掉size。只有在容器析构的下,才会自由内存。
改的法子:在调用DataNode的Clear方法的地方转移呢展示调用他的析构函数~DataNode()方式来析构其中间的map和vector成员。

1.3 测试证明

贪图2-6 12分钟内存变化曲线

相比之下前面曲线,减少满了部分,说明修改中。是否有任何内存泄漏情况,使用Valgrind继续进行测试。

希冀2-7 3独消息之泄露分析汇总

祈求2-8 12只信息之透漏分析汇总

坐第三方库使用问题,存在内存泄漏,但是并其并从未发生变化。分析该出口其他内存信息,也尚无可疑的地方,问题之彻底解决陷入迷茫。

2 double linked导致单元测试core

2.1 问题讲述

在化解问题1时常,曾经提交调用DataNode的Clear方法。在跑单元测试用例时,有微量的代码会core,位置为和改无关之python调用处:

图2-9 double linked 导致core

2.3 问题解决

早年底更,double
linked一般还是地下内存读写引起。使用Valgrind是可以检查来,确实DataNode相关的内存确实存在非法读写。
先实现方式:DataNode管理类和指向应buffermanager都是单例的,并且通过静态变量,而那析构不叫程序员控制,其内存以有关联系统导致。
修改:DataNode管理类保持单例不换,buffermanager修改为DataNode管理类的分子,由其负责buffer的生命周期。
改后,运行单元测试正常,问题解决。

3 内存问题终极定位

3.1 问题讲述

假如图2-6所显示,在化解了内存泄漏后,内存还是回落而无法用valgrind检测,是为什么也?

3.2 问题浅析

valgrind的泄露是检测从启动暨离,检测出无主内存泄漏情况。而且动用Valgrind运行工作程序,程序是异常要紧的卡顿,不切合长日子和大量压力运行。从剖析来拘禁,业务经过在运转过程被,可能是不断申请内存,在脱过程遭到放出。例如map或者vector等容器。
开班探索:

  • 1
    乎尝尝用getrusage来测试成内存,能觉察内存变大,却无计可施稳定位置。getrusage显示maxrss是因块方式示。
getrusage测试
  • 2 走查怀疑代码。因为代码量大,无目的的走查是老大没用的。
  • 3
    利用二瓜分法屏蔽组件方式来压缩范围后,在走查。屏蔽代码可能造成事情不通,未必会检索有题目。
    需另外辟路,有同事推荐gperftools来同样试。

3.3 问题解决

google-perftools提供heap_checker功能(https://gperftools.github.io/gperftools/heap\_checker.html)。

  • 1 首先是安装gperftools。
  • 2 重新编译业务代码添加 -ltcmalloc 链接tcmalloc库。
  • 3 启动平台,因为经过需要独自启动。

env HEAPCHECK=normal HEAP_PROFILE_ALLOCATION_INTERVAL=104857600
HEAPPROFILE=”/home/hunter/log/test.log” ZSmartOCPro IN

征:HEAPPROFILE指定生成dump文件之职务;HEAP_PROFILE_ALLOCATION_INTERVAL,程序外存每增长就无异于数值之后就是dump
一差内存,默认是1G, 104857600=100M

内存dump文件

  • 4 利用pprof来分析内存文件

/usr/local/bin/pprof –text –base=/home/hunter/log/test.log.0003.heap
/home/hunter/bin/ZSmartOCPro /home/hunter/log/test.log.0009.heap

外存差异

快速定位来问题所在,和猜测一直。业务代码写过程漏了调用vector的复位,导致直接增长。

改问题后再也测试后,发现解决内存差异问题。

/home/hunter/log>/usr/local/bin/pprof –text
–base=/home/hunter/log/test.log.0020.heap
/home/hunter/bin/ZSmartOCPro /home/hunter/log/test.log.0055.heap
Using local file /home/hunter/bin/ZSmartOCPro.
Using local file /home/hunter/log/test.log.0055.heap.
Total: -0.0 MB
0.0 -272.7% -272.7% 0.0 -272.7%
std::_Vector_base::_M_create_storage (inline)
0.0 -218.2% -490.9% 0.0 -218.2% Json::Value::Value
0.0 -109.1% -600.0% 0.0 -109.1% TariffTemplate::Instance (inline)
0.0 -109.1% -709.1% 0.0 -109.1% list_resize (inline)
0.0 -109.1% -818.2% 0.0 -109.1% std::vector::push_back (inline)
0.0 -4.5% -822.7% 0.0 -4.5%
std::__cxx11::basic_string::_M_mutate
0.0 -4.5% -827.3% 0.0 -4.5% zmq::msg_t::init_size
0.0 -0.0% -827.3% -0.0 109.1% AcmManager::Initialize
0.0 -0.0% -827.3% 0.0 -109.1% AcmManager::RetrieveAccumulation
0.0 -0.0% -827.3% 0.0 -109.1% AcmManager::RetrieveDataFromTableAcm

至此,问题彻底解决。

小结

盖工具实现原理的出入,在解决问题经常为各发生专长:

  • Valgrind:适合解决非法读写,无主内存泄露等问题一定。
  • gperftools:长期运行过程内存使用量应是平安的,gperftools适合发现运行过程中内存差异,提供泄露的函数范围。而且本着影响影响小,适合高压力快速复现。
  • getrusage:虽然对于定位问题帮助不酷,但是得用来守护进程监控管理业务过程的内存以情况。
    如上是应用工具解决问题的经过,供就学与参考。感谢同事拉并定位和缓解。