mysql常用資料結構介紹(1)
mem_root
mysql層通過mem_root管理記憶體分配,防止頻繁分配和釋放小記憶體。
mem_root的定義見include/my_alloc.h:
typedef struct st_mem_root
{
USED_MEM *free; 空閒連結串列,分配空間時先檢查該連結串列有沒有剩餘空間,如果沒有,再分配新空間
USED_MEM *used; 已經分配完成的連結串列空間,該連結串列中的資料空間幾乎沒有剩餘可用空間
USED_MEM *pre_alloc; 預先分配的塊
size_t min_malloc; 如果一個USED_MEM塊中可用空間left小於該值,這個塊放入used連結串列中
size_t block_size; 初始塊的大小
unsigned int block_num; 塊的數目
unsigned int first_block_usage; 空閒連結串列中第一個塊檢查的次數,如果超過MAX_BLOCK_USAGE_BEFORE_DROP,該塊會被放入used連結串列中void (*error_handler)(void);
} MEM_ROOT;typedef struct st_used_mem
{ /* struct for once_alloc (block) */
struct st_used_mem *next; /* Next block in use */
unsigned int left; /* memory left in block */
unsigned int size; /* size of block */
} USED_MEM;
該結構主要有兩個連結串列: free和used。 每個連結串列使用USED_MEM作為資料節點,資料節點中存有空間總大小和未使用的空間大小。新建一個數據節點時,先新增到free連結串列中,隨著空間的分配,資料節點中未使用空間大小left小於閾值min_malloc,該資料節點新增到used連結串列中。分配空間時,先從free連結串列中檢查有沒有可用的空間,如果沒有,再分配新的塊。
相關的函式:
init_alloc_root: 初始化mem_root物件。如果pre_alloc_size不為0,預先建立一個數據塊,free和pre_alloc指向這個資料塊。
alloc_root
該函式先檢查free連結串列的首個數據塊,如果該資料塊連續ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP(10)次不滿足分配條件,並且該塊小於ALLOC_MAX_BLOCK_TO_DROP(4K),將該塊移動到used連結串列中。
依次檢查free連結串列中剩餘空間大於length的資料塊。如果不存在這樣的資料塊,新建一個數據塊。注意新建資料塊的大小如下,可以看到分配的空間大小會趨向于越來越大:
block_size= mem_root->block_size * (mem_root->block_num >> 2); 預設大小,block_num每增加4,分配的記憶體大小增加block_size
get_size= length+ALIGN_SIZE(sizeof(USED_MEM)); 分配請求的空間大小
get_size= MY_MAX(get_size, block_size); 取最大值
修改該資料塊的left剩餘空間,如果left剩餘空間小於min_malloc,加入到used連結串列的表頭。
reset_root_defaults:
該函式設定block_size和pre_alloc塊。如果沒有符合要求的pre_alloc塊,遍歷free連結串列,查詢符合要求的資料塊,如果發現完全沒有使用的資料塊,free該塊的空間。如果最後沒有找到,新建一個符合要求的塊。
free_root: 清空分配的資料塊
MY_MARK_BLOCKS_FREE: used連結串列中的資料庫合併到free連結串列中,並且所有資料塊中資料清空(left設定為初始塊大小)。最終結果:free連結串列指向所有的資料塊,used連結串列中空。沒有向作業系統釋放空間
MY_KEEP_PREALLOC:只保留pre_alloc塊,其他塊的空間都釋放給作業系統。
參考:https://www.cnblogs.com/justfortaste/p/3198406.html