今天读到一篇 关于 Firefox 内存优化的文章 ,里面提到使用 jemalloc 时遇到的一个小问题,不知道有没有现成的 API 可以统计,回头看看。

Jemalloc 是用来减少内存碎片化导致的内存损失的。内存碎片化是指可用内存被分成了一片片碎片,虽然总量够用,但是无法按需求分出指定大小的块。操作系统是按页(page)进行内存管理的,每页被浪费的内存会成为空洞;另外,部分释放回来的内存会在已分配内存间形成碎片,比较大的内存申请也塞不进去碎片里,导致内存损失

[Page1, [3 Free], PageXXX, [4 Free]]

比如上图里一共有 7 个单位的可用空间,但是被分为了 3 和 4 个单位,当需要分配 5 个单位时就没法分了

Jemalloc 的技巧就是将内存分配规整为不同大小的类别,然后将这些不同大小的内存块分配到连续的内存空间上。当内存释放后,相似大小的请求可以复用旧内存块,减少碎片。这种设计会因为分配请求对齐到 2 的幂上而浪费一部分空间,极端情况下会浪费 50% 的空间。比如,17 个字节的分配请求会拿到 32 字节的块,1025 的请求会拿到 2048 的块。为了统计内存使用情况,arena 留了一部分字做簿记信息,导致 4KB 的内存申请总是拿到 8KB 的块

按理说 jemalloc 不应该犯如此低级的错误,看 jemalloc 的手册 能确认的是 17 会对齐到 32,但是 1025 只会对齐到 1280 的,不知道是不是将这个 Bug 修好了。回头试试将内存分配的请求都打印下来跑个统计看看

update: 找到作者Nicholas Nethercote的原文了,好想要NN那个内存分配日志的脚本。。。

又及:云风也写过一篇类似的blog,有空还是自己打下日志看看,估算一下slop的大小吧