这一次是关于内存使用的分析
int main (int argc, char **argv) { //....................... //....................... //....................... slabs_init(settings.maxbytes, settings.factor, preallocate); //....................... //....................... //....................... } void slabs_init(const size_t limit, const double factor, const bool prealloc) { int i = POWER_SMALLEST - 1; unsigned int size = sizeof(item) + settings.chunk_size; mem_limit = limit; // 一个记录slab数据的结构体 memset(slabclass, 0, sizeof(slabclass)); while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) { /* Make sure items are always n-byte aligned */ // 取整 if (size % CHUNK_ALIGN_BYTES) size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); // 一个slab大小为1MB // 定出一个item的大小 slabclass[i].size = size; // 定出每一个slab有多少个item数量 slabclass[i].perslab = settings.item_size_max / slabclass[i].size; // 下一种slab的item大小为当前的的factor倍,一般为1.25 size *= factor; } // 最后一种slab。每一个item为item_size_max,一般为1MB,每个slab只有一个item power_largest = i; slabclass[power_largest].size = settings.item_size_max; slabclass[power_largest].perslab = 1; } // 分配一个新的slab出来 static int do_slabs_newslab(const unsigned int id) { slabclass_t *p = &slabclass[id]; int len = settings.slab_reassign ? settings.item_size_max : p->size * p->perslab; char *ptr; if ( (mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) || // 如果没有超出mem_limit (grow_slab_list(id) == 0) || // 判断这种slab,是否需要变大list_size // 并且grow_slab_list返回1 ((ptr = memory_allocate((size_t)len)) == 0) // // 则调用memory_allocate分配一个slab的内存 ) { return 0; } memset(ptr, 0, (size_t)len); split_slab_page_into_freelist(ptr, id); // 将新分配的内存放到slots中,也就是空闲列表中 // add this new slab in the array of slab list p->slab_list[p->slabs++] = ptr; mem_malloced += len; return 1; } // slab的数组增长 static int grow_slab_list (const unsigned int id) { slabclass_t *p = &slabclass[id]; if (p->slabs == p->list_size) { size_t new_size = (p->list_size != 0) ? p->list_size * 2 : 16; // 初始大小16,然后以后不够用了,增大一倍 void *new_list = realloc(p->slab_list, new_size * sizeof(void *)); if (new_list == 0) return 0; p->list_size = new_size; p->slab_list = new_list; } return 1; } // 我需要一个item,分一个给我吧 static void *do_slabs_alloc(const size_t size, unsigned int id) { slabclass_t *p; void *ret = NULL; item *it = NULL; p = &slabclass[id]; assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0); //要么sl_curr空闲列表为空,不为空时slots指向的头一个item的cslid值必须为0 //如果空闲列表不为空,直接从空闲列表中分配 //如果空闲列表为空,则do_slabs_newslab来增加该slabclass的slabs if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) { /* We don't have more memory available */ ret = NULL; } else if (p->sl_curr != 0) { /* return off our freelist */ it = (item *)p->slots; p->slots = it->next; if (it->next) it->next->prev = 0; p->sl_curr--; ret = (void *)it; } if (ret) { p->requested += size; MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret); } else { MEMCACHED_SLABS_ALLOCATE_FAILED(size, id); } return ret; } // free并不是将内存返回给系统,而是将不使用的item占用的空间重新放到相对应的slabclass的slots中 static void do_slabs_free(void *ptr, const size_t size, unsigned int id) { slabclass_t *p; item *it; p = &slabclass[id]; it = (item *)ptr; it->it_flags |= ITEM_SLABBED; it->prev = 0; it->next = p->slots; if (it->next) it->next->prev = it; p->slots = it; // 把这个item放到slot中。上面是一连串双向链表的操作 p->sl_curr++; p->requested -= size; return; }