经典的内存池技术

经典的内存池(MemPool)技术,是一种用于分配大量大小相同的小对象的技术。通过该技术可以极大加快内存分配/释放过程。下面我们详细解释其中的奥妙。

经典的内存池只涉及两个常量:MemBlockSize、ItemSize(小对象的大小,但不能小于指针的大小,在32位平台也就是不能小于4字节),以及两个指针变量MemBlockHeader、FreeNodeHeader。开始,这两个指针均为空。

class MemPool
{
private:
    const int m_nMemBlockSize;
    const int m_nItemSize;
 
    struct _FreeNode {
        _FreeNode* pPrev;
        BYTE data[m_nItemSize - sizeof(_FreeNode*)];
    };
 
    struct _MemBlock {
        _MemBlock* pPrev;
        _FreeNode data[m_nMemBlockSize/m_nItemSize];
    };
 
    _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)串成一个链。

这段话涉及两个关键概念:内存块(MemBlock)自由内存结点(FreeNode)。内存块大小一般固定为MemBlockSize字节(除去用以建立链表的指针外)。内存块在申请之初就被划分为多个内存结点(Node),每个Node大小为ItemSize(小对象的大小),计MemBlockSize/ItemSize个。这MemBlockSize/ItemSize个内存结点刚开始全部是自由的,他们被串成链表。我们看看申请/释放内存过程,就很容易明白这样做的目的。

申请内存过程代码如下:

void* MemPool::malloc()    // 没有参数
{
    if (m_pFreeNodeHeader == NULL)
    {
       const int nCount = m_nMemBlockSize/m_nItemSize;
        _MemBlock* pNewBlock = new _MemBlock;
        pNewBlock->data[0].pPrev = NULL;
        for (int i = 1; i < nCount; ++i)
            pNewBlock->data[i].pPrev = &pNewBlock->data[i-1];
        m_pFreeNodeHeader = &pNewBlock->data[nCount-1];
        pNewBlock->pPrev = m_pMemBlock;
        m_pMemBlock = pNewBlock;
    }
    void* pFreeNode = m_pFreeNodeHeader;
    m_pFreeNodeHeader = m_pFreeNodeHeader->pPrev;
    return pFreeNode;
}

内存申请过程分为两种情况:

  1. 在自由内存结点链表(FreeNodeList)非空。在此情况下,Alloc过程只是从链表中摘下一个结点的过程。
  2. 否则,意味着需要一个新的内存块(MemBlock)。这个过程需要将新申请的MemBlock切割成多个Node,并把它们串起来,MemPool技术的开销主要在这。
释放内存过程, 只是把要释放的结点挂到自由内存链表(FreeNodeList)的开头即可:

void MemPool::free(void* p)
{
    _FreeNode* pNode = (_FreeNode*)p;
    pNode->pPrev = m_pFreeNodeHeader;
    m_pFreeNodeHeader = pNode;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值