memcache記憶體池的設計原理
阿新 • • 發佈:2018-12-27
memcache中管理記憶體的資料結構如下:
typedef struct {
unsigned int size; /* sizes of items */
unsigned int perslab; /* how many items per slab */
void **slots; /* list of item ptrs */
unsigned int sl_total; /* size of previous array*/
unsigned int sl_curr; /* first free slot */
void *end_page_ptr; /* pointer tonext free item at end of page, or0*/
unsigned int end_page_free; /* number of items remaining at end of last alloced page */
unsigned int slabs; /* how many slabs were allocated for this class */
void **slab_list; /*array of slab pointers */
unsigned int list_size; /* size of prev array*/
unsigned int killing; /* index+1 of dying slab, or zero if none */
} slabclass_t;
程式中有一個全域性的陣列
static slabclass_t slabclass[POWER_LARGEST + 1]用於儲存slab,預分配記憶體池時呼叫的是void slabs_init(const size_t limit, const double factor) 函式,其中limit是記憶體池的最大容量,factor是分配時的增長因子.
比方說,加入factor是2,第一個在slabclass陣列中的slab的每個item大小是128位元組,那麼下一個slab每個item的大小就是128*2,再下一個就是128*2*2(注意,為了簡化問題的說明,上面沒有考慮地址對齊的因素).
在預分配記憶體池時,最多給每個slab儲存item的容量是1M記憶體,這個數值由#define POWER_BLOCK 1048576決定.
因此,slab中的幾個元素在預分配記憶體時是這麼定的:
size有一個起始值,這個值以後的增長由factor決定,增長的過程前面已經闡述過了;
perslab儲存的是一個slab存放的item數量,因此perslab = POWER_BLOCK / slabclass[i].size;
如果預先分配一段記憶體供使用的話,也就是沒有定義DONT_PREALLOC_SLABS巨集,那麼就呼叫slabs_preallocate進行預分配記憶體.
其中,end_page_ptr指向這個預分配好的指標,end_page_free表示的是目前空閒可用item的數量,在預分配時,這個值與perslab相同.
在這個記憶體池模型中,每個page實際上是一個數組,陣列中每個元素的大小就是這個slab中item的大小.
另外,slots儲存的是釋放出來的item指標,sl_total表示總的數量,sl_curr表示的是目前可用的已經釋放出來的item數量.
每一次要分配記憶體的時候,首先根據需要分配的記憶體大小在slabclass陣列中查詢索引最小的一個大於所要求記憶體的slab,如果slots不為空,那麼就從這裡返回記憶體,否則去查詢end_page_ptr,如果也沒有,那麼就只能返回NULL了.
每一次釋放記憶體的時候,同樣的找到應該返回記憶體的slab元素,改寫前面提到的slot指標和sl_curr數.
有點倉促,以後再完善~~
typedef struct {
unsigned int size; /* sizes of items */
unsigned int perslab; /* how many items per slab */
void **slots; /* list of item ptrs */
unsigned int sl_total; /* size of previous array*/
unsigned int sl_curr; /* first free slot */
void *end_page_ptr;
unsigned int end_page_free; /* number of items remaining at end of last alloced page */
unsigned int slabs; /* how many slabs were allocated for this class */
void **slab_list; /*array of slab pointers */
unsigned int list_size; /* size of prev
unsigned int killing; /* index+1 of dying slab, or zero if none */
} slabclass_t;
程式中有一個全域性的陣列
static slabclass_t slabclass[POWER_LARGEST + 1]用於儲存slab,預分配記憶體池時呼叫的是void slabs_init(const size_t limit, const double factor) 函式,其中limit是記憶體池的最大容量,factor是分配時的增長因子.
比方說,加入factor是2,第一個在slabclass陣列中的slab的每個item大小是128位元組,那麼下一個slab每個item的大小就是128*2,再下一個就是128*2*2(注意,為了簡化問題的說明,上面沒有考慮地址對齊的因素).
在預分配記憶體池時,最多給每個slab儲存item的容量是1M記憶體,這個數值由#define POWER_BLOCK 1048576決定.
因此,slab中的幾個元素在預分配記憶體時是這麼定的:
size有一個起始值,這個值以後的增長由factor決定,增長的過程前面已經闡述過了;
perslab儲存的是一個slab存放的item數量,因此perslab = POWER_BLOCK / slabclass[i].size;
如果預先分配一段記憶體供使用的話,也就是沒有定義DONT_PREALLOC_SLABS巨集,那麼就呼叫slabs_preallocate進行預分配記憶體.
其中,end_page_ptr指向這個預分配好的指標,end_page_free表示的是目前空閒可用item的數量,在預分配時,這個值與perslab相同.
在這個記憶體池模型中,每個page實際上是一個數組,陣列中每個元素的大小就是這個slab中item的大小.
另外,slots儲存的是釋放出來的item指標,sl_total表示總的數量,sl_curr表示的是目前可用的已經釋放出來的item數量.
每一次要分配記憶體的時候,首先根據需要分配的記憶體大小在slabclass陣列中查詢索引最小的一個大於所要求記憶體的slab,如果slots不為空,那麼就從這裡返回記憶體,否則去查詢end_page_ptr,如果也沒有,那麼就只能返回NULL了.
每一次釋放記憶體的時候,同樣的找到應該返回記憶體的slab元素,改寫前面提到的slot指標和sl_curr數.
有點倉促,以後再完善~~