記憶體池的實現 一

2021-06-17 15:42:41 字數 2261 閱讀 7693

**:

引言

c/c++下記憶體管理是讓幾乎每乙個程式設計師頭疼的問題,分配足夠的記憶體、追蹤記憶體的分配、在不需要的時候釋放記憶體——這個任務相當複雜。而直接使用系統呼叫malloc/free、new/delete進行記憶體分配和釋放,有以下弊端:

呼叫malloc/new,系統需要根據「最先匹配」、「最優匹配」或其他演算法在記憶體空閒塊表中查詢一塊空閒記憶體,呼叫free/delete,系統可能需要合併空閒記憶體塊,這些會產生額外開銷

頻繁使用時會產生大量記憶體碎片,從而降低程式執行效率

容易造成記憶體洩漏

記憶體池(memory pool)是代替直接呼叫malloc/free、new/delete進行記憶體管理的常用方法,當我們申請記憶體空間時,首先到我們的記憶體池中查詢合適的記憶體塊,而不是直接向作業系統申請,優勢在於:

比malloc/free進行記憶體申請/釋放的方式快

不會產生或很少產生堆碎片

可避免記憶體洩漏

記憶體池設計

看到記憶體池好處這麼多,是不是恨不能馬上拋棄malloc/free,投奔記憶體池的懷抱呢?且慢,在我們自己動手實現記憶體池之前還需要明確以下幾個問題:

記憶體池的空間如何獲得?是程式啟動時分配一大塊空間還是程式執行中按需求分配?

記憶體池對到來的記憶體申請,有沒有大小的限制?如果有,最小可申請的記憶體塊為多大,最大的呢?

如何合理設計記憶體塊結構,方便我們進行記憶體的申請、追蹤和釋放呢?

記憶體池占用越多空間,相對應其他程式能使用的記憶體就越少,是否要設定記憶體池空間的上限?設定為多少合適呢?

帶著以上問題,我們來看以下一種記憶體池設計方案。

記憶體池實現方案一

首先給出該方案的整體架構,如下:

圖1.記憶體池架構圖

結構中主要包含block、list 和pool這三個結構體,block結構包含指向實際記憶體空間的指標,前向和後向指標讓block能夠組成雙向鍊錶;list結構中free指標指向空閒 記憶體塊組成的鍊錶,used指標指向程式使用中的記憶體塊組成的鍊錶,size值為記憶體塊的大小,list之間組成單向鍊錶;pool結構記錄list鍊錶的頭和尾。

記憶體跟蹤策略

該方案中,在進行記憶體分配時,將多申請12個位元組,即實際申請的記憶體大小為所需記憶體大小+12。在多申請的12個位元組中,分別存放對應的list指標(4位元組)、used指標(4位元組)和校驗碼(4位元組)。通過這樣設定,我們很容易得到該塊記憶體所在的list和block,校驗碼起到粗略檢查是否出錯的作用。該結構圖示如下:

圖2.記憶體塊申請示意圖

圖中箭頭指示的位置為記憶體塊真正開始的位置。

記憶體申請和釋放策略

申請:根據所申請記憶體的大小,遍歷list鍊錶,檢視是否存在相匹配的size;

存在匹配size:檢視free時候為null

free為null:使用malloc/new申請記憶體,並將其置於used所指鍊錶的尾部

free不為null:將free所指鍊錶的頭結點移除,放置於used所指鍊錶的尾部

不存在匹配size:新建list,使用malloc/new申請記憶體,並將其置於該list的used所指鍊錶尾部

返回記憶體空間指標

釋放:根據記憶體跟蹤策略,獲取list指標和used指標,將其從used指標所指的鍊錶中刪除,放置於free指標所指向的鍊錶

對方案一的分析

對照「記憶體池設計」一節中提出的問題,我們的方案一有以下特點:

程式啟動後記憶體池並沒有記憶體塊,到程式真正進行記憶體申請和釋放的時候才接管記憶體塊管理;

該記憶體池對到來的申請,對申請大小並不做限制,其為每個size值建立鍊錶進行記憶體管理;

該方案沒有提供限定記憶體池大小的功能

結合分析,可以得出該方案應用場景如下:程式所申請的記憶體塊大小比較固定(比如只申請/釋放1024bytes或2048bytes的記憶體),申請和釋放的頻率基本保持一致(因申請多而釋放少會占用過多記憶體,最終導致系統崩潰)。

reference: 《記憶體池設計研究與應用》by freeeyes

分類: 

記憶體池標籤: 

記憶體池

記憶體池 簡單的記憶體池的實現

當頻繁地用malloc申請記憶體,然後再用free釋放記憶體時,會存在兩個主要問題。第乙個問題是頻繁的分配釋放記憶體可能導致系統記憶體碎片過多 第二個問題是分配釋放記憶體花費的時間可能比較多 這個問題不太明顯 這個時候我們就可以考慮使用記憶體池了。最樸素的記憶體池思想就是,首先你向系統申請一塊很大的...

記憶體池簡單實現(一)

記憶體池就是在程式啟動時,預先向堆中申請一部分記憶體,交給乙個管理物件。在程式執行中,需要時向管理物件 借 不需要時 還 給管理物件。原理很簡單,關鍵是怎樣才能高效地 借 還 在c s伺服器中,需要頻繁地收發資料報。而資料報的記憶體採用原始的new delete模式,會大大降低伺服器效能,所以想到了...

記憶體池實現

記憶體池實現 話說一直想找乙個別人寫好的使用,可惜沒什麼人會拿這小東西發布,只好自寫乙個。1.多級鍊錶分配池 我不知道這種設計的具體學名是什麼,這部分的內容也許你去看 stl原始碼分析 的有關章節更合適一些,這裡我只能用我粗陋的語言描述一下。記憶體池,完全可以從字面上理解為從池子裡申請記憶體,釋放的...