代码改变世界

内存池技术解释

2008-07-29 14:15  ubunoon  阅读(1906)  评论(0编辑  收藏  举报

说明:
      本文是在网上查看了相关技术课题及解说后做的一个笔记与摘录,关键在于描述这么一种思想。

经典的内存池(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       forint 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便是采用预测模型来实现的。