几种malloc实现原理 ptmalloc(glibc) && tcmalloc(google) && jemalloc(facebook)

最近公司的线上代码出现了持续性的内存增长,已经恶化到需要定时重启来解决。使用valgrind检测不出内存泄露,自己写了一个类似bound checker内存泄露的检测工具(更小更灵活),倒是track到一些泄露,但仍然不符合泄露的量级。最后估计到有可能是glibc的内存分配机制导致的内存碎片问题,heap的孔洞很多,但free的时候并不能归还到操作系统,于是对市面上的一些malloc进行调研,分析其内存管理机制,希望在替换malloc后问题得到改善。

系统结构

系统下经典内存布局如上,程序起始的1GB地址为内核空间,接下来是向下增长的栈空间和向上增长的mmap地址。而堆地址是从底部开始,去除ELF、数据段、代码段、常量段之后的地址并向上增长。纵观各种内存布局,对于大内存各种malloc基本上都是直接mmap的。而对于小数据,则通过向操作系统申请扩大堆顶,这时候操作系统会把需要的内存分页映射过来,然后再由这些malloc管理这些堆内存块,减少系统调用。而在free内存的时候,不同的malloc有不同的策略,不一定会把内存真正地还给系统,所以很多时候,如果访问了free掉的内存,并不会立即Run Time Error,只有访问的地址没有对应的内存分页,才会崩掉。

Ptmalloc (glibc 的malloc实现)

小内存分配与释放

在ptmalloc中采用chunk进行小内存管理,并且把相似(相同)大小的chunk组织在一个链表中进行维护,这个链表叫做bin。 前64个bin中组织的chunk大小按8个字节递增,这一块叫做 small_bin。 之后的就是large_bin, large_bin中的chunk是先按size,size相同则按照最近使用时间排列,这样要搜索一个可用的内存时,就在bins里按大小搜索,返回一个最小可用的chunk。

chunk结构如下图所示。可以理解成链表中一个node。存储了上一个相邻的chunk的大小以及flag,还有下一个chunk的“指针”。 flag A 表示是不是在主分配去,M表示是否是mmap得到的, P表示上一个chunk是否在使用中。

在free的时候,ptmalloc会检查附近的chunk,如果标志位为P,即空闲中,会尝试把连续空闲的chunk合并成一个大的chunk,放到unstored bin里。但是当很小的chunk释放的时候,ptmalloc会把它并入fast bin中。同样,某些时候,fast bin里的连续内存块会被合并并加入到一个unsorted bin里,然后再才进入普通bin里。所以malloc小内存的时候,是先查找fast bin,再查找unsorted bin,最后查找普通的bin,如果unsorted bin里的chunk不合适,则会把它扔到bin里。

大内存分配与释放

Ptmalloc的分配的内存顶部还有一个top chunk,如果前面的bin里的空闲chunk都不足以满足需要,就是尝试从top chunk里分配内存。如果top chunk里也不够,就要从操作系统里拿了,这样会造成heap增大。
 
还有就是特别大的内存,会直接从系统mmap出来,不受chunk管理,这样的内存在回收的时候也会munmap还给操作系统。

总结

  1. 分配与释放
    1. 小内存:(相当于实现了自身的cache,速度快)
      1. 分配:[获取分配区(arena)并加锁] -> fast bin -> unsorted bin -> small bin -> large bin -> top chunk -> 扩展堆 (brk分配)
      2. 释放:brk分配的内chunk list,只能从top开始线性向下释放。释放掉中间的chunk,无法归还给OS(内存孔洞),而是并链入到了bins/fast bins的容器中。
    2. 大内存: (与os直接打交道,速度慢)
      1. 分配:mmap从操作系统获得
      2. 释放:munmap归还给操作系统
  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值