前言上一節只分析了第二級配置器是由多個鍊錶來存放相同記憶體大小, 當沒有空間的時候就向記憶體池索取就行了, 卻沒有具體分析記憶體池是怎麼儲存空間的, 是不是記憶體池真的有用不完的記憶體, 本節我們就具體來分析一下
記憶體池static data template的初始化
template char *__default_alloc_template::start_free = 0; // 記憶體池的首位址
template char *__default_alloc_template::end_free = 0; // 記憶體池的結束位址
template size_t __default_alloc_template::heap_size = 0; // 多次呼叫記憶體池, 就會更多的是給鍊錶分配記憶體, 這就是乙個增量.
這裡**注釋寫的很清楚了, 我就提取出來分析一下吧
記憶體池的大小大於需要的空間, 直接返回起始位址(nobjs預設設定為20, 所以每次呼叫都會給鍊錶額外的19個記憶體塊)記憶體池的記憶體不足以馬上分配那麼多記憶體, 但是還能滿足分配乙個即以上的大小, 那就全部分配出去
如果乙個物件的大小都已經提供不了了, 先將零碎的記憶體塊給乙個小記憶體的鍊錶來儲存, 然後就準備呼叫malloc申請40塊+額外大小的記憶體塊(額外記憶體塊就由heap_size決定), 如果申請失敗跳轉到步驟4, 成功跳轉到步驟6
充分利用更大記憶體的鍊錶, 通過遞迴來呼叫他們的記憶體塊
如果還是沒有記憶體塊, 直接呼叫一級配置器來申請記憶體, 還是失敗就丟擲異常, 成功申請就繼續執行
重新修改記憶體起始位址和結束位址為當前申請的位址塊, 重新呼叫chunk_alloc分配記憶體
// 記憶體池
template char* __default_alloc_template::chunk_alloc(size_t size, int& nobjs)
// 記憶體池的記憶體不足以馬上分配那麼多記憶體, 但是還能滿足分配乙個即以上的大小, 那就按對齊方式全部分配出去
else if (bytes_left >= size)
else
start_free = (char *)malloc(bytes_to_get);
// 記憶體不足了
if (0 == start_free)
}// 如果一點記憶體都沒有了的話, 就只有呼叫一級配置器來申請記憶體了, 並且使用者沒有設定處理例程就丟擲異常
end_free = 0; // in case of exception.
start_free = (char *)malloc_alloc::allocate(bytes_to_get);
}// 申請記憶體成功後重新修改記憶體起始位址和結束位址, 重新呼叫chunk_alloc分配記憶體
heap_size += bytes_to_get;
end_free = start_free + bytes_to_get;
return(chunk_alloc(size, nobjs));
}
}
總結
記憶體池的存在就是為了能快速的提供我們做需要的記憶體並且儲存多餘的空間, 讓stl分配空間不再每次都進行malloc和free的操作, 效率又很有保障. 有時使用者申請的塊更小, 我們也能充分的利用起來. 唯一可能不足的是我們每次只申請char
個大小, 但是記憶體池獲得的確是8位元組的大小.
leveldb原始碼分析之記憶體池Arena
這篇部落格主要講解下leveldb記憶體池,記憶體池很多地方都有用到,像linux核心也有個記憶體池。記憶體池的存在主要就是減少malloc或者new呼叫的次數,較少記憶體分配所帶來的系統開銷。arena類採用vector來儲存每次分配記憶體的指標,每一次分配的記憶體,我們稱為乙個塊block。bl...
山寨STL實現之記憶體池
記憶體池的作用 減少記憶體碎片,提高效能。首先不得不提的是win32和x64中對於指標的長度是不同的,在win32中乙個指標佔4位元組,而在x64中乙個指標佔8位元組。也正是不清楚這一點,當我在x64中將指標作為4位元組修改造成其他資料異常。首先我們先來定義三個巨集 define align siz...
STL 記憶體池原始碼學習與思考
首先說明一下,這次學習的是stl空間配置器的原始碼中記憶體池部分的函式,下面是原始碼 template char default alloc template threads,inst s chunk alloc size t size,int nobjs else if bytes left si...