memcached內存分配策略源碼分析

本文基於memcached 1.2.0寫成php

memcached的內存分配器slab.c不過300行代碼,仍是比較容易上手分析的。git

內存模型以下: github

一個slabclass_t管理了多個slab,每一個slab被稱爲內存頁,每一個slab管理多個item的內存空間

核心函數

函數名 做用
slabs_init 初始化slabclass_t結構體數組
slabs_clsid 經過內存大小從slabclass_t數組中找到最小能知足的結構體
slabs_preallocate 給每一個slabclass_t先分配一個slab(頁)的內存(1mb)
slabs_newslab 給指定的slabclass分配一個新的slab存放到slab_list上,同時slabs、end_page_ptr、end_page_free發生相應變化
grow_slab_list 動態增長slab_list數組的大小
slabs_alloc 從內存分配器中取出一個空的item內存來使用
slabs_free 將item所在的內存指針從新標記成可以使用,至關於刪除了item
slabs_stats 從slabclass_t結構體上獲取內存分配器的使用狀況

其中被slab.c之外的文件調用的函數有slabs_alloc、slabs_free、slabs_init和slabs_stats數組

slabs_init內部調用關係

slabs_alloc內部調用關係

內存分配生命週期

初始化機制-slabs_init()函數

  1. 計算每一個item的初始佔用的內存大小
unsigned int size = sizeof(item) + settings.chunk_size;
複製代碼
  1. 根據size值和每一個內存頁1mb大小算出當前slabclass_t的每一個slab可以存放多少個item放到perslab屬性上
  2. 按照factor這個縮放值增大size(size=size*factor)繼續初始化下一個slabclass_t

獲取item的內存機制-slabs_alloc()函數

這裏有一個分支,若是當前slabclass的當前slab還有剩餘的內存空間,直接就分配了,參考:memcached

if (! (p->end_page_ptr || p->sl_curr || slabs_newslab(id)))
    return 0;
複製代碼

三種狀況函數

  1. 當前頁還有內存空間 p->end_page_ptr
  2. 有item被刪除了釋放的空間p->sl_curr
  3. 給當前的slabclass_t分配一個新頁 slabs_newslab(id)
/* return off our freelist, if we have one */
if (p->sl_curr)
    return p->slots[--p->sl_curr];

/* if we recently allocated a whole page, return from that */
if (p->end_page_ptr) {
    void *ptr = p->end_page_ptr;
    if (--p->end_page_free) {
        p->end_page_ptr += p->size;
    } else {
        p->end_page_ptr = 0;
    }
    return ptr;
}
複製代碼

刪除item的內存釋放機制

主要就是把刪除的item放進slabclass_t的slots數組中,申請內存時,優先從這個slots中獲取,達到這個memcached解決內存碎片的目的ui

這裏有個對這個存放被刪除的item的slots數組擴容的操做spa

if (p->sl_curr == p->sl_total) { /* need more space on the free list */
    int new_size = p->sl_total ? p->sl_total*2 : 16;  /* 16 is arbitrary */
    void **new_slots = realloc(p->slots, new_size*sizeof(void *));
    if (new_slots == 0)
        return;
    p->slots = new_slots;
    p->sl_total = new_size;
}
複製代碼

能夠看到這個slots數組初始容量是16,後續每都是按照2倍容量進行擴容的.net

一些注意的點

memcached的源代碼命名不規範,可能在閱讀源碼上形成極大的干擾3d

註釋不清楚具備迷惑性

memcached使用注意事項

  1. 每一個value大小不能超過1mb,能夠修改POWER_BLOCK宏,從新編譯memcached
  2. memcache是不會調用free函數釋放內存的

參考資料

  1. blog.csdn.net/initphp/art…
  2. blog.csdn.net/luotuo44/ar…
  3. holmeshe.me/cn/understa…
  4. holmeshe.me/cn/understa…
  5. holmeshe.me/cn/understa…

持續更新中...

相關文章
相關標籤/搜索