這一次是關於內存使用的分析數組
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; }