目前市面上有不少分析Jemalloc老版本的博文,但5.3.0却少之又少。而且5.3.0的架构与之前的版本也有较大不同,本着“与时俱进”、“由浅入深”的宗旨,我将逐步分析Jemalloc5.3.0的实现。
另外,单讲实现代码是极其枯燥的,我将尽量每个原理知识点都用一个简简单单的小程序引出来,这样便于大家测试和上手调试。另外,还会用GDB打印数据结构,方便理解当时的状态。
无论jemalloc还是ptmalloc不会用户申请多少字节内存就分配多少,而是多分配一点,比如当用户要分配10个字节内存时实际会分配16字节,当用户要分配12个字节内存时实际也会分配16字节,要求20字节则会分配32字节。
写个简单的代码,多次分配10个字节,计算返回的地址之差看看是多少?
//gcc malloc_diff.c `jemalloc-config --libdir`/libjemalloc.a `jemalloc-config --libs` -g
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
void* p;
for(int i=0;i<100;i++) //tcache bin
{
p=malloc(10);
printf("addr of ith allocation:%p\n", p);
}
return 0;
}
正如预期,两两相差16。(程序刚开始两次分配相差16,但时间长了可就不一定了)。侧面印证了实际分配了16字节。
这个概念在jemalloc里叫size classes, 用户请求都会被round up到某个稍大一点的size, 那么jemalloc 5.3.0里都有哪些size class哪?偷个懒,直接用GDB把size表打出来。
并不是只有50个,在我的64位机器上其实有232个(SC_NSIZES)。
前36个被归类为small size class, 后面的归类为large size class. 以前还有huge, 但现在没有了。
sz_index2size_tab的初始化过程如下:
读者如有兴趣,可以推一推怎么得出的各个值。
有两个函数能实现index与size的互转: