一种内存池的实现方法

基本的数据结构

大图: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);
posted @ 2018-06-23 16:28  BruceChen7  阅读(690)  评论(0编辑  收藏  举报