**
[url]
[align=center][b]概述[/b][/align]
記憶體池(mempool)技術備受推崇。我用google搜尋了下,沒有找到比較詳細的原理性的文章,故此補充乙個。另外,補充了boost::pool元件與經典mempool的差異。同時也描述了mempool在sgi-stl/stlport中的運用。
[align=center][b]經典的記憶體池技術[/b][/align]
經典的記憶體池(mempool)技術,是一種用於分配大量大小相同的小物件的技術。通過該技術可以極大加快記憶體分配/釋放過程。下面我們詳細解釋其中的奧妙。
經典的記憶體池只涉及兩個常量:memblocksize、itemsize(小物件的大小,但不能小於指標的大小,在32位平台也就是不能小於4位元組),以及兩個指標變數memblockheader、freenodeheader。開始,這兩個指標均為空。
class mempool
;struct _memblock ;
_memblock* m_pmemblockheader;
_freenode* m_pfreenodeheader;
public:
mempool(int nitemsize, int nmemblocksize = 2048)
: m_nitemsize(nitemsize), m_nmemblocksize(nmemblocksize),
m_pmemblockheader(null), m_pfreenodeheader(null)
};
其中指標變數memblockheader是把所有申請的記憶體塊(memblock)串成乙個鍊錶,以便通過它可以釋放所有申請的記憶體。freenodeheader變數則是把所有自由記憶體結點(freenode)串成乙個鏈。
這段話涉及兩個關鍵概念:[color=red]記憶體塊(memblock)[/color]和[color=red]自由記憶體結點(freenode)[/color]。記憶體塊大小一般固定為memblocksize位元組(除去用以建立鍊錶的指標外)。記憶體塊在申請之初就被劃分為多個記憶體結點(node)1,每個node大小為itemsize(小物件的大小),計memblocksize/itemsize個。這memblocksize/itemsize個記憶體結點剛開始全部是自由的,他們被串成鍊錶。我們看看申請/釋放記憶體過程,就很容易明白這樣做的目的。
[align=center][b]申請記憶體過程[/b][/align]
**如下:
void* mempool::malloc() // 沒有引數
void* pfreenode = m_pfreenodeheader;
m_pfreenodeheader = m_pfreenodeheader->pprev;
return pfreenode;
}
記憶體申請過程分為兩種情況:
在自由記憶體結點鍊錶(freenodelist)非空。在此情況下,alloc過程只是從鍊錶中摘下乙個結點的過程。
否則,意味著需要乙個新的記憶體塊(memblock)。這個過程需要將新申請的memblock切割成多個node,並把它們串起來,mempool技術的開銷主要在這。
[align=center][b]釋放記憶體過程[/b][/align]
**如下:
void mempool::free(void* p)
釋放過程極其簡單,只是把要釋放的結點掛到自由記憶體鍊錶(freenodelist)的開頭即可。
[align=center][b]效能分析[/b][/align]
mempool技術申請記憶體/釋放記憶體均極其快(比autofreealloc慢)。其記憶體分配過程多數情況下複雜度為o(1),主要開銷在freenodelist為空需要生成新的memblock時。記憶體釋放過程複雜度為o(1)。
[b]boost::pool[/b]
boost::pool是記憶體池技術的變種。主要的變化如下:
memblock改為非固定長度(memblocksize),而是:第1次申請時m_nitemsize*32,第2次申請時 m_nitemsize*64,第3次申請時m_nitemsize*128,以此類推。不採用固定的memblocksize,而採用這種做法**模型2,是乙個細節上的改良。
增加了ordered_free(void* p) 函式。ordered_free區別於free的是,free把要釋放的結點掛到自由記憶體鍊錶(freenodelist)的開頭, ordered_free則假設freenodelist是有序的,因此會遍歷freenodelist把要釋放的結點插入到合適的位置。我們已經看到,free的複雜度是o(1),非常快。但請注意ordered_free是比較費的操作,其複雜度是o(n)。這裡n是freenodelist的大小。對於乙個頻繁釋放/申請的系統,這個n很可能是個大數。這個boost描述得很清楚:
注意:不要認為boost提供ordered_free是多此一舉。後文我們會在討論boost::object_pool時解釋這一點。
[align=center][b]基於記憶體池技術的通用記憶體分配元件[/b][/align]
[size=medium][color=red]sgi stl把記憶體池(mempool)技術進行發揚光大,用它來實現其最根本的allocator。
其大體的思想是,建立16個mempool,<=8位元組的記憶體申請由0號mempool分配,<=16位元組的記憶體申請由1號 mempool分配,<=24位元組的記憶體有2號mempool分配,以此類推。最後,>128位元組的記憶體申請由普通的malloc分配。[/color][/size]
[align=center][b]記憶體池技術的缺陷[/b][/align]
遺憾的是,mempool技術可能導致記憶體占用只增不減。還沒有非常有效的辦法去避免這種情況的發生。不過我後來在scopealloc的實現中發現blockpool(是乙個簡化版的記憶體池)反倒避免了這一缺陷。
[align=center][b]注意[/b][/align]
以上**屬於偽**(struct _freenode、_memblock編譯通不過),並且去除了出錯處理。
[b]footnotes[/b]
1. boost:pool/object_pool 中稱之為塊(chunk)。
2. 是的,這是一種使用者記憶體需求的**模型,其實std::vector的記憶體增長亦採用了該模型。
記憶體池 MemPool 技術詳解
記憶體池 mempool 技術備受推崇。我用google搜尋了下,沒有找到比較詳細的原理性的文章,故此補充乙個。另外,補充了boost pool元件與經典mempool的差異。同時也描述了mempool在sgi stl stlport中的運用。經典的記憶體池 mempool 技術,是一種用於分配大量...
記憶體池 MemPool 技術詳解
記憶體池 mempool 技術備受推崇。我用google搜尋了下,沒有找到比較詳細的原理性的文章,故此補充乙個。另外,補充了boost pool元件與經典mempool的差異。同時也描述了mempool在sgi stl stlport中的運用。經典的記憶體池 mempool 技術,是一種用於分配大量...
記憶體池 MemPool 技術詳解
概述 記憶體池 mempool 技術備受推崇。我用google搜尋了下,沒有找到比較詳細的原理性的文章,故此補充乙個。另外,補充了boost pool元件與經典mempool的差異。同時也描述了mempool在sgi stl stlport中的運用。經典的記憶體池 mempool 技術,是一種用於分...