說明:
本文是在網上查看了相關技術課題及解說後做的一個筆記與摘錄,關鍵在於描述這麼一種思想。
經典的記憶體池(Memory pool)技術是擷取及釋放相同大小的記憶體塊單元對象的技術,其優點在於快速擷取記憶體以及快速釋放記憶體。
經典記憶體池技術通常需要四個變數外部變數來管理記憶體單元,分別是記憶體塊大小(總的記憶體塊),最小記憶體塊大小(由於指標等關係,一般要求最小記憶體塊單元大於sizeof(void*)個位元組,即4個位元組),一個指向記憶體塊首地址的指標和一個指向空閑記憶體塊首地址的指標。具體實現結構如下:
1class MemeoryPool
2{
3 private:
4 const int m_nMemBlockSize;
5 const int m_nItemSize;
6
7 struct _FreeNode
8 {
9 _FreeNode *pPrev;
10 BYTE data[m_nItemSize - sizeof(_FreeNode *) ];
11 };
12 struct _MemBlock
13 {
14 _MemBlock *pPrev;
15 _FreeNode data[m_nMemBlockSize / m_nItemSize];
16 };
17
18 _MemBlock *m_pMemBlockHeader;
19 _FreeNode *m_pFreeNodeHeader;
20
21 public:
22 MemoryPool( int nItemSize, inte nMemBlockSize=2048)
23 : m_nItemSize(nItemSize)
24 , m_nMemBlockSize(nMemBlockSize)
25 , m_pMemBlockHeader(NULL)
26 , m_pFreeNodeHeader(NULL)
27 {}
28 public:
29 void* malloc()
30 void* free()
31};
32
33void *MemoryPool::malloc()
34{
35 if( m_pFreeNodeHeader == NULL ) // 第一次申請記憶體
36 {
37 const int nCount = m_nMemBlockSize / m_nItemSize;
38 _MemBlock *pMemBlock = new _MemBlock;
39 pMemBlock->data[0].pPrev = NULL;
40 for( int i=1; i<nCount; ++i )
41 {
42 pMemBlock->data[i].pPrev = &pMemBlock->data[i-1];
43 }
44 m_pFreeNodeHeader = &pMemBlock->data[nCount-1]; // 指向記憶體塊尾部
45 pMemBlock->pPrev = m_pMemBlock; // 對於第一次而言就是NULL,對於後來再次申請而言,則是前一個記憶體位址了!
46 m_pMemBlock = pMemBlock;
47 }
48 void *pFreeNode = m_pFreeNodeHeader;
49 m_pFreeNodeHeader = m_pFreeNodeHeader->pPrev;
50 return pFreeNode;
51}
52
53void *MemoryPool::free() // 將最後一塊記憶體釋放到空閑記憶體塊地區中去
54{
55
56 }
此處實現的記憶體池技術採用的是定長的最小塊單元,是一個功能比較簡單的記憶體塊實現單元。
效能分析:
此處擷取記憶體,除了第一次需要調用new操作以及設定指標等操作,花費較多時間,new操作需要調用系統功能,花費時間較大,指標初始化操作也需要花費較長時間,但其後每次申請記憶體單元的複雜度均為O(1),析構記憶體單元的複雜度也為O(1),因此與直接申請記憶體相比,記憶體池技術對記憶體的申請以及釋放均有較快的速度,並且,由於記憶體池一次性申請是一大塊記憶體(否則就不能稱之為池了),將減少系統中的記憶體片段。當然由於記憶體池技術需要額外的指標來指示記憶體單元的使用方式,因此,記憶體池技術對於少量記憶體使用量的程式其空間利用率是比較低的。A coin has two faces!
在stl設計中,大量使用了記憶體池技術(採用new以及new placement技術來實現),通過allocator類封裝來實現,模板技術可以方便的擷取最小記憶體對象塊的大小,設定記憶體單元塊數目就可以知道m_nMemBlockSize的大小了,而且可以動態改變。
上述的記憶體池技術中採用的是定長的記憶體單元塊申請,對於需要大量記憶體單元的程式,該方式所能夠提供的節省時間將減少,為了使得程式能夠節省更多時間,採用具有動態申請記憶體(從系統中)的方法,即第一次申請1KB,第二次申請2KB,第三次申請4KB,第四次申請8KB,在需要大記憶體單元的時候,程式依然可以節省大量大量時間。由於該方法在電腦中廣泛使用,便有了一個名字:預測模型。stl中vector便是採用預測模型來實現的。