memcached内存分配原理及相应源码解析
memcached默认情况下是采用Slab Allocator的机制分配、管理内存,此原理相当简单,将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合),如下图(借鉴于《memcached全面剖析》):
关于此块的初始化逻辑划分的源码在memcached.c文件中:
void slabs_init(const size_t limit, const double factor, const bool prealloc) {
……//此处省略很多行
while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) {
if (size % CHUNK_ALIGN_BYTES)
size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES);
slabclass[i].size = size;
slabclass[i].perslab = settings.item_size_max / slabclass[i].size;
size *= factor;
if (settings.verbose > 1) {
fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n",
i, slabclass[i].size, slabclass[i].perslab);
}
}
power_largest = i;
slabclass[power_largest].size = settings.item_size_max;
slabclass[power_largest].perslab = 1;
……//此处省略很多行
}
如上面的代码部分,POWER_LARGEST表示的是可以分配的chunk组数,默认的是200;settings.item_size_max是表示最大的item大小,也即chunk块的默认最大值,默认值是1024* 1024,这两个值都是直接写死在程序里,没有配置文件可供配置。 factor是chunk大小的增长因子,在启动memcached的时候有-f参数来指定。
上边size的大小初始化为size = sizeof(item) + settings.chunk_size;(其中 settings.chunk_size默认为48),所以从下面的代码:
if (size % CHUNK_ALIGN_BYTES)
size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES);
最小的chunk大小也会>=56;
第一组的chunk信息就是,每个chunk的大小: slabclass[i].size = size;
本组内chunk的个数为: slabclass[i].perslab = settings.item_size_max / slabclass[i].size;
第二主信息:
个数的算法也同样
……
最后一组,
slabclass[power_largest].size = settings.item_size_max;
slabclass[power_largest].perslab = 1;
即一组只有一个chunk,大小为设置的最大值。
如果在使用的时候,你发现你的应用场景1M大小的chunk根本不够存储你的一个item,此时,我们需要做的就是修改原文件中settings.item_size_max;的值,位置在memcached.c文件的setting_init(void)函数中;比如我的修改值128 * 1024 * 1024; //64M
-vv模式启动memcached:
slab class 1: chunk size 160032 perslab 838
slab class 2: chunk size 240048 perslab 559
slab class 3: chunk size 360072 perslab 372
slab class 4: chunk size 540112 perslab 248
slab class 5: chunk size 810168 perslab 165
slab class 6: chunk size 1215256 perslab 110
slab class 7: chunk size 1822888 perslab 73
slab class 8: chunk size 2734336 perslab 49
slab class 9: chunk size 4101504 perslab 32
slab class 10: chunk size 6152256 perslab 21
slab class 11: chunk size 9228384 perslab 14
slab class 12: chunk size 13842576 perslab 9
slab class 13: chunk size 20763864 perslab 6
slab class 14: chunk size 31145800 perslab 4
slab class 15: chunk size 46718704 perslab 2
slab class 16: chunk size 70078056 perslab 1
slab class 17: chunk size 134217728 perslab 1