日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一种高效快速的内存池实现(附源码)

發(fā)布時(shí)間:2025/3/15 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一种高效快速的内存池实现(附源码) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

此算法靈感來自于apache內(nèi)存池實(shí)現(xiàn)原理,不過讀者如果沒有看過apache內(nèi)存池實(shí)現(xiàn)也無關(guān)系,因?yàn)楸舅惴ㄏ鄬?duì)apache內(nèi)存池算法更為簡(jiǎn)單而且易懂,個(gè)人認(rèn)為某些場(chǎng)合也更為高效,或許真正到了apache服務(wù)器上性能不如,但是這套設(shè)計(jì)思想應(yīng)該還是可以借鑒到更多場(chǎng)合的。

?

我們?cè)谡{(diào)用malloc函數(shù)時(shí),操作系統(tǒng)內(nèi)部會(huì)查找一個(gè)所謂的空閑鏈表,當(dāng)找到足夠大的空閑空間時(shí)會(huì)將內(nèi)存分割并返回一部分會(huì)用戶,當(dāng)然在很大的項(xiàng)目里面有可能會(huì)出現(xiàn)鏈表所有節(jié)點(diǎn)都找不到空閑空間的情形,此時(shí)操作系統(tǒng)便會(huì)不斷搜索內(nèi)存碎片,然后組合成一段足夠大的空間并返回,如果此時(shí)還找不到便返回NULL。所以在new或者malloc調(diào)用后程序員有必要對(duì)申請(qǐng)的內(nèi)存做是否為NULL的判斷。而且在調(diào)用free后系統(tǒng)有可能還要合并內(nèi)存產(chǎn)生額外開銷,另外不斷的malloc和free也會(huì)產(chǎn)生很多內(nèi)存碎片并給操作系統(tǒng)管理內(nèi)存帶來很大的壓力。所以說內(nèi)存池算法在很多場(chǎng)合是非常必須的。

該內(nèi)存池結(jié)構(gòu)可以初步理解成一個(gè)二維數(shù)組,每個(gè)元素都是內(nèi)存塊。每個(gè)內(nèi)存塊都有一段附帶的數(shù)據(jù)信息,代表這塊內(nèi)存在整個(gè)二維數(shù)組中的位置。申請(qǐng)和釋放的時(shí)候可以根據(jù)附帶信息直接找到內(nèi)存塊在內(nèi)存池也就是這個(gè)二維數(shù)組中的位置。

?

以上A1到A8為例,假設(shè)整個(gè)內(nèi)存池序列有n個(gè),也就是A1到An,絕對(duì)會(huì)存在m(1<=m<=n),保證A1到Am為空閑狀態(tài),Am到An為被使用狀態(tài)。

?

也就是說,如果內(nèi)存池A1到An全部沒有被使用,當(dāng)申請(qǐng)內(nèi)存時(shí),只需要檢查A1是否為空閑狀態(tài)即可。有的可以返回,如果不是空閑,說明整個(gè)A序列內(nèi)存都已經(jīng)被占用了。當(dāng)A1空閑,那么申請(qǐng)內(nèi)存后將A1狀態(tài)標(biāo)記為被使用狀態(tài),然后將A1和An調(diào)換,此時(shí)保證內(nèi)存池前n-1為未使用狀態(tài),n為使用狀態(tài)。同樣的道理,再次申請(qǐng)則將調(diào)整后的A1和A(n-1)調(diào)換,保證A1到A(n-2)為空閑狀態(tài),最后兩個(gè)元素為被使用狀態(tài)。

?

釋放內(nèi)存時(shí),假設(shè)內(nèi)存池序列是A1到Am為空閑,A(m+1)到An為被使用,而被使用的內(nèi)存肯定是隨機(jī)在m+1到n的某個(gè)元素,那么將其標(biāo)記為未使用狀態(tài)之后馬上與m+1這個(gè)元素調(diào)換,此時(shí)保證A1到A(m+1)空閑,后A(m+2)到An為未使用。

?

所以說內(nèi)存池中不管怎么申請(qǐng)釋放或者調(diào)整,始終保證A1到Am空閑,之后的為被使用狀態(tài)。如果中間有元素太長(zhǎng)時(shí)間沒被使用而釋放,此時(shí)也需要根據(jù)這規(guī)則做調(diào)整。因?yàn)檫@樣申請(qǐng)內(nèi)存時(shí)不需要查表就可以找到元素,而釋放內(nèi)存時(shí)也能根據(jù)內(nèi)存池管理數(shù)據(jù)結(jié)構(gòu)中的外部和內(nèi)部索引一步找到內(nèi)存池中的位置,這也是該內(nèi)存池高效的原因之一。

?

內(nèi)存塊附帶的數(shù)據(jù)結(jié)構(gòu)如下:

struct MemPoolData {unsigned int dwMemTrunkTicket;unsigned char chbIsMemTrunkUsed;unsigned char chOutIndex;unsigned char chInIndex; };

?

其中包含了該內(nèi)存塊是否被占用,上次使用時(shí)間戳以及在二維數(shù)組中的位置。

?

那么按照以上規(guī)則,假如說A1A8已經(jīng)滿員而且全都沒有被使用,再次申請(qǐng)8字節(jié)內(nèi)存時(shí),首先檢查A1這塊內(nèi)存是否已經(jīng)被使用,如果被使用就無法申請(qǐng)。但是如果沒有被使用則返回給程序,標(biāo)記此內(nèi)存已經(jīng)被使用。然后將A8內(nèi)存和A1調(diào)換,記錄一個(gè)索引7代表A1A7沒有被使用,A7以后的數(shù)據(jù)被使用了。同樣的道理再次申請(qǐng)時(shí)仍然直接檢查A1因?yàn)闆]被使用則返回給程序,再將A1A7調(diào)換,此時(shí)A1A6沒有被使用,A6A8被使用了。釋放內(nèi)存時(shí),假如說A1A3未被使用而A4A8使用,釋放的內(nèi)存是A6則將A6標(biāo)記為未使用狀態(tài),將A4A6調(diào)換即可。

?

另外如果申請(qǐng)和釋放內(nèi)存時(shí),系統(tǒng)函數(shù)會(huì)鎖住整個(gè)內(nèi)存管理隊(duì)列,而這套算法只會(huì)鎖住當(dāng)前大小序列,也就是說,申請(qǐng)8字節(jié)大小和申請(qǐng)16字節(jié)大小內(nèi)存時(shí)不會(huì)產(chǎn)生鎖競(jìng)爭(zhēng)。因?yàn)?字節(jié)大小操作只是鎖住A序列,16大小則是鎖住圖上的B序列。每個(gè)序列都有自己獨(dú)立的鎖。這也是高效快速的原因之一。以上就是申請(qǐng)和釋放內(nèi)存的基本思想,但是實(shí)際上向下的數(shù)組和自己實(shí)現(xiàn)和vector類似的容器,這樣可以自動(dòng)拓展,具體實(shí)現(xiàn)方法可以參考內(nèi)存池源碼。

?

源碼:MemPoolTest.zip

轉(zhuǎn)載于:https://www.cnblogs.com/mod109/p/5004474.html

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的一种高效快速的内存池实现(附源码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。