一种内存池的实现方法
基本的数据结构
大图:https://drive.google.com/file/d/1s5Y_xPB_k-gOXxC1iwG60Jx0kb8yyQ1b/view?usp=sharing
基本设计
- 将内存按照1KB, 2KB, 4KB, 8KB, 16KB, 64KB, 128KB, 256KB, 512KB, 1Mb, 2MB, 4MB, 8MB,16MB, 32MB来分配
- 在释放时,将申请的内存缓存到内存池中,这样下次申请相同大小的内存可以直接获取,但是是否一定要缓存到内存池中,要看其已经缓存的内存池的数量,如果太多了,那么直接释放掉。
- 在申请大于32MB的内存时,直接使用operator delete/free来释放,小于32MB的内存,其分配实际的大小要大于其给定的数值,比如申请1234字节的内存,应该将分配的大小设定为2KB。
- 要设计线程安全的内存池,使用互斥量来保护核心的数据结构。
- 可以在每块分配的内存中加入BLOCK_HEADER,来对其进行校验,验证申请释放内存是否合理。
申请内存过程
这里使用python的代码,来解释
# size 是调用者意欲分配的内存大小
def allocate(size):
# 如果这里分配的大小大于了最大缓存的size:直接通过malloc/operatornew 申请
if size > max_pooled_size:
use_malloc_or_operator_new(size);
return;
# 将意欲分配的size提升到匹配的size
size = ImproveSize(size)
# 获取对应size大小的index
index = GetIndexBySize(size)
# 如果内存池中有空闲该大小的内存
if not memory_pool[index].empty():
# 返回该地址
return memory_pool[index].pop_back();
else:
use_malloc_or_operator_new(size)
释放内存过程
释放内存的过程,重点分支有两个:一个是分配的大小大于32MB,那么直接释放,如果小于32MB,那么应该返回到内存池中,但也不是无条件的返回到内存池,当内存池中该size的内存过多时,也应该释放。
def free(p):
# 该block太大,那么就应该直接释放
if BlockIsLargeThanMaxSize(p):
use_free_or_operator_delete(p);
else if currentBlockCachedNumMoreThanMax():
use_free_or_operator_delete(p);
else:
memory_pool[index].push_back(p)
cached_num++;
这种实现,对于每一刻分配的内存,都有一个头,来表示上下文,比如当前分配的大小,在内存池中idx大小,这样在是释放的时候,根据头的信息,能够方便是释放或缓存到内存池中。
c++中使用operator new 和operator delete来申请和释放内存
size_t new_size = sizeof(BLOCK_HEADER) + size;
BLOCK_HEADER* p = static_cast<BLOCK_HEADER*>(operator new(new_size));
p->Magic[0] = 'M';
p->Magic[1] = 'P';
p->Index = -1;
p->Size = size;
// 和 operator delete
operator delete(block);
AtomicIncrement(&m_dwDeleteCount);
坚持一步一个脚印的去实现自己的梦想!