引子
在某些工作负载中,随着时间的推移,内存的使用会逐渐增长,直到 OOM。后面发现是内存碎片问题,而将系统默认的内存分配器(glibc malloc)换成 jemalloc ,能有效控制内存的增长上界。
为了解其背后原理,便找来 jemalloc 最初的论文:A Scalable Concurrent malloc(3) Implementation for FreeBSD 来一探究竟。当然,相比 2006 年论文发表时,当前的 jemalloc 可能已经发生了很大改变,因此本文只对当时论文内容负责。更多 jemalloc 机制,大家可以去其 github 仓库查看文档和源码。
背景
在探讨论文的主要思路之前,我们先简单回顾下内存分配器(memory allocator)的作用和边界。简言之:
- 对下,向操作系统申请大块内存(使用
sbrk
、mmap
等系统调用) - 对上,处理应用层的各种尺寸的内存申请请求(
malloc(size)
),并在应用层“表示”不用(free
)后进行释放
往小了说,分配器的功能非常简单:分配和释放(malloc 和 free)。想象中,实现也应该很简单,只需利用一个表来记录所有已使用内存和未分配内存( a bit of bookkeeping),然后:
- malloc 请求来了,先去空闲表中找,不够的话就问操作系统要
- free 请求来了,还回空闲表中,如果空的多了,就还给操作系统