一種內存池的實現方法
阿新 • • 發佈:2018-06-23
返回 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);
一種內存池的實現方法