glibc内存泄露以及TCmalloc 简单分析
最近开发一个私人程序时碰到了严重的内存问题,具体表现为:进程占用的内存会随着访问高峰不断上升,直到发生OOM被kill为止。我们使用valgrind等工具进行检查发现程序并无内存泄露,经过仔细调查我们发现时glibc的内存管理机制导致的,下次将发文对此深入解释,本文只列出核心的几个要素:
1. glibc在多线程内存分配的场景下为了减少lock contention,会new出很多arena出来,每个线程都有自己默认的arena,但是内存申请时如果默认arena被占用,则round-robin到下一个arena。
2. 每个arena的空间不可直接共享和互相借用,除非通过主arena释放给操作系统然后被各个辅助arena重新申请。
3. glibc归还内存给OS有一个很苛刻的条件就是top chunk必须是free的,否则,即使应用程序已经释放了大片内存,glibc也不会将这些内存归还给OS。
在我们的场景中常常是thread A alloc一片空间,最后由thread B free,所以这就造成各个arena之间及其不平衡,加上苛刻的内存归还条件,在整个程序运行过程中,占用内存几乎从未下降过,区别仅仅是缓慢上涨和快速上涨。
由此我们实验了tcmalloc,具体介绍见:http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html
安装过程见其中的INSTALL文件,下面简略说一下:
1. install libunwind : git clone git://git.sv.gnu.org/libunwind.git
2. download : http://google-perftools.googlecode.com/files/google-perftools-1.7.tar.gz
3. ./configure --enable-frame_pointers && make && sudo make install
4. sudo ldconfig
5. g++ .... -ltcmalloc (link static lib)
tcmalloc每个线程默认最大缓存16M空间,所以当线程多的时候其占用的空间还是非常可观的,在common.h中有几个参数是控制缓存空间的,可以做合理的修改(只可个人做实验,注意法律问题):
1. 降低每个线程的缓存空间,
可以修改common.h中的kMaxThreadCacheSize,比如2M
2. 降低所有线程的缓存空间的总大小,可以修改common.h中的kDefaultOverallThreadCacheSize,比如20M
3. 尽快将free的空间还给central list,可以将kMaxOverages改小一点,比如1
还可以定期让tcmalloc归还空间给OS,
#include "google/malloc_extension.h" MallocExtension::instance()->ReleaseFreeMemory(); |
实验结果证明,tcmalloc分配速度的确快,而且程序不再像以前那样内存只增不减。
上面Sanjay的文章已经对tcmalloc做了个大概的介绍,我看了一下tcmalloc的核心code,下面将其分配和释放的过程简单介绍一下:
线程申请资源:
1. 首先根据申请空间的大小从当前线程的可用内存块里面找(每个进程维护一组链表,每个链表代表一定大小的可用空间)
2. 如果step 1没有找到,则到central list里面查找(central list跟线程各自维护的list结构很像,为不同的size各自维护一组可用空间列表)
3. 如果step 2 central list也没有找到,则计算分配size个字节需要分配多少page(变量:class_to_pages)
4. 根据pagemap查找page对应的可用的span列表,如果找到了,则直接返回span,central list会将该span切割成合适的大小放入对应的列表中,然后交给thread cache
5. 如果step 4没有找到可用的span,则向OS直接申请,然后步骤同step 4。
注意的是tcmalloc向系统申请空间有三种方式:sbrk,mmap,/dev/mem文件,默认是三种都try的,一种不行换另外一种。
线程释放资源:
1. 释放某个object
2. 找到该object所在的span
3. 如果该span中所有object都被释放,则释放该span到对应的可用列表,在释放的过程中,尝试将该span跟左右spans merge成更大的span
4. 如果当前thread cache的free 空间大于指定预置,归还部分空间给central list
5. central list也会试图通过释放可用span列表的最后几个span来将不用的空间归还给OS
tcmalloc向OS申请/释放资源是以span为单位的。
tcmalloc里面不少实现值得称道,比如pagesize到void*的mapping方式,添加/移除链表元素的时候利用结构体内存布局直接赋值,span/page/item的内存层次结构等,值得一看。
glibc内存泄露以及TCmalloc 简单分析的更多相关文章
- 读书摘要观后感与总结:《Glibc内存管理:ptmalloc2源代码分析》
更新中 在Linux平台下做漏洞利用的时候,针对于Heap部分总是有些不求甚解,下面开个博文来记录下<Glibc内存管理:ptmalloc2源代码分析>这本书的读后感和收获,一些简单的点将 ...
- Linux下利用Valgrind工具进行内存泄露检测和性能分析
from http://www.linuxidc.com/Linux/2012-06/63754.htm Valgrind通常用来成分析程序性能及程序中的内存泄露错误 一 Valgrind工具集简绍 ...
- C++对象模型与内存位对齐的简单分析(GNU GCC&VS2015编译器)
以Fruit和Apple为例进行分析: Fruit和Apple的定义如下: 通过在两种编译环境下的测试(GNU GCC & VS2015),可以发现这两种编译器的对象模型是一样的,如下图所示: ...
- _CrtDumpMemoryLeaks报告程序中的内存泄露问题(简单示例代码)
// .h 文件 #pragma once class CConsoleDump { public: explicit CConsoleDump(LPCTSTR lpszWindowTitle = N ...
- 【转】.. Android应用内存泄露分析、改善经验总结
原文网址:http://wetest.qq.com/lab/view/107.html?from=ads_test2_qqtips&sessionUserType=BFT.PARAMS.194 ...
- ThreadLocal是否会引发内存泄露的分析(转)
这篇文章,主要解决一下疑惑: 1. ThreadLocal.ThreadLocalMap中提到的弱引用,弱引用究竟会不会被回收? 2. 弱引用什么情况下回收? 3. JAVA的ThreadLocal和 ...
- ThreadLocal是否会引发内存泄露的分析 good
这篇文章,主要解决一下疑惑: 1. ThreadLocal.ThreadLocalMap中提到的弱引用,弱引用究竟会不会被回收? 2. 弱引用什么情况下回收? 3. JAVA的ThreadLocal和 ...
- Java宝典(四)------Java中也存在内存泄露。
--Java中会存在内存泄露吗? --如果你想当然的以为Java里有了垃圾回收机制就不会存在内存泄露,那你就错了. Java里也会存在内存泄露! 我们慢慢来分析. 所谓内存泄露就是指一个不再被程序使用 ...
- 【翻译】JavaScript内存泄露
原文地址:http://javascript.info/tutorial/memory-leaks#tools 我们在进行JavaScript开发时,很少会考虑内存的管理.JavaScript中变量的 ...
随机推荐
- MFC项目依赖 BCG框架示例
1.创建一个简单的MFC工程: 2.将BCG框架项目导入到新建的mfc解决方案中,例如将BCGCBPro\BCGCBPRO140.vcxproj添加到解决方案. 3.修改mfc项目属性,包含BCG框架 ...
- webpack4基本配置
1.npm init 生成package.json文件 2.npm install webpack webpack-cil --save-dev 安装webpack和webpack-cli ...
- mybatis <forEach>标签的使用
MyBatis<forEach>标签的使用 你可以传递一个 List 实例或者数组作为参数对象传给 MyBatis.当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中,用名 ...
- Eclipse字体修改
第一步: 第二步: 第三步: 第四步: 第五步: 第六步:
- PHP.14-图片处理类
图片处理类 test.php <?php include "images.class.php"; $image=new Image("./images/" ...
- 10 class封装 ORM
1.版本1:初始化 # -*- coding:utf-8 -*- from MySQLdb import * class MysqlHelper: def __init__(self,host,por ...
- Oracle 11g数据库安装与卸载的方法图解(windows)
一.Oracle 11g安装 安装之前要先确定自己的电脑配置,以windows为例,如果是win7以下系统如xp等,可以选择Oracle 10g.因为10g的程序文件只有200多兆,而11g及达到了2 ...
- laravel5.5中间件
目录 1. 中间件知识 1. artisan 命令 2. 文件内容 3. 前置中间件和后置中间件 4. 使用中间件 2. 控制器中间件 1. 中间件知识 1. artisan 命令 php artis ...
- 【HTML&CSS】 第二章:标准模式下的页面与怪异模式下的页面区别
盒模型 前面提到,盒模型(box mode)是浏览器 Quirks Mode 和 Standards Mode 的主要区别. 描述 对于“盒模型”一词并没有明确的文档定义,它是开发人员描述 CSS 中 ...
- 剑指Offer - 九度1523 - 从上往下打印二叉树
剑指Offer - 九度1523 - 从上往下打印二叉树2013-12-01 00:35 题目描述: 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 输入: 输入可能包含多个测试样例,输入以E ...