1. 程式人生 > >一種內存池的實現方法

一種內存池的實現方法

返回 memory 內存 cast oca ID incr count delet

基本的數據結構

技術分享圖片

大圖: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);

一種內存池的實現方法