server层内存管理
数据结构
1 2 3 4
| struct Block { Block *prev{nullptr}; /** Previous block; used for freeing. */ }; Block 是MEM_ROOT的子类
|
Block 的prev 指的都是历史Block, 已经分配完内存的Block
m_max_capacity 为0,表示不限制
m_allocated_size表示的使用的block 合起来的size
Block 内部结构
要求my_memory_head小于32个字节
内存申请流程
申请block内部
其中“设置当前block” ,
1 2 3 4 5 6 7 8 9
| char *new_mem = pointer_cast<char *>(new_block) + ALIGN_SIZE(sizeof(*new_block));
new_block->prev = m_current_block; m_current_block = new_block;
m_current_free_start = new_mem + length; m_current_free_end = new_mem + new_block_size;
|
插入现有blockchain
1 2
| new_block->prev = m_current_block->prev; m_current_block->prev = new_block;
|
其中有个细节, 当申请big内存时, 会将blocksize 增加1/2
这个里面有一点内存浪费逻辑
当内存不够时,并且新申请的内存小于blocksize时, 当前block会变成历史block, 历史block 基本上内存用
Claim
MEM_ROOT Claim 会对每个Block 进行Claim
而Block->claim, 主要是设置PSI
1 2 3 4 5 6 7 8 9 10
| void my_claim(const void *ptr) { my_memory_header *mh;
if (ptr == NULL) return;
mh = USER_TO_HEADER(ptr); DBUG_ASSERT(mh->m_magic == MAGIC); mh->m_key = PSI_MEMORY_CALL(memory_claim)(mh->m_key, mh->m_size, &mh->m_owner); }
|
Clear
如果设置了MY_MARK_BLOCKS_FREE或MY_KEEP_PREALLOC标记位, 则root->ClearForReuse();
否则直接调用root->Clear
ClearForReuse 和Clear 主要的区别就是, 对当前block的处理, Reuse 会重新使用当前Block, 而clear会清理当前Block
Clear
1 2 3 4 5 6 7 8 9
| Block *start = m_current_block;
m_current_block = nullptr; m_block_size = m_orig_block_size; m_current_free_start = &s_dummy_target; m_current_free_end = &s_dummy_target; m_allocated_size = 0;
FreeBlocks(start);
|
ClearForReuse
1 2 3 4 5 6 7
| m_current_free_start = pointer_cast<char *>(m_current_block) + ALIGN_SIZE(sizeof(*m_current_block)); Block *start = m_current_block->prev; m_current_block->prev = nullptr; m_allocated_size = m_current_free_end - m_current_free_start;
FreeBlocks(start);
|
Block 内部
内存申请/释放都是走my_malloc/my_free/my_realloc, 这几个函数比较简单, 就是申请一块内存,然后将内存header设置相应的数据