zoukankan      html  css  js  c++  java
  • 内存池完整实现代码及一些思考

       为了提高效率和有效的监控内存的实时状态,我们采取了内存池的思想来解决效率与对内存实现监控的问题。

    网上查找到了一些方案,根据自己的理解实现了应用。

       我们什么时候要调用到内存池,

       1,当我们频繁的申请释放同样数据大小的内存空间,我们可以用比动态new更有效方式来管理内存时,我们应该用内存池来提高效率。

       2,当我们需要知道内存实时的申请状态,以便于对于服务器内存状态做实时预警时,我们可以用内存池的接口,来给内存增加监控。

    实现的特点:

       1,内存池内存单元大小可以动态定义,实现多级内存池。

       2,申请效率很高,单元测试下是普通new/delete的4倍左右,当然具体性能还应机器类别而异。 

        

    MemoryPool.h 的实现
    //该内存池理论来自于IBM文章,http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html
    //作者冯宏华,徐莹,程远,汪磊享有论文著作权,由2011-06-06 konyel lin根据相关代码和理论进行优化修改。

    #include <string>
    #include <malloc.h>
    //内存对齐值,可以根据机器取指长度进行设置
    #define MEMPOOL_ALIGNMENT 4

    #define USHORT unsigned short
    #define ULONG unsigned long

    struct MemoryBlock
    {
      USHORT nSize;
      USHORT nFree;
      USHORT nFirst;
      USHORT nDummyAlign1;
      MemoryBlock* pNext;
      char aData[1];
      static void* operator new(size_t,USHORT nTypes, USHORT nUnitSize){
         return ::operator new(sizeof(MemoryBlock) + nTypes * nUnitSize);
      }
      static void operator delete(void *p, size_t){
          ::operator delete (p);
      }
      MemoryBlock (USHORT nTypes = 1, USHORT nUnitSize = 0);
      ~MemoryBlock() {}
    };

    class MemoryPool
    {
       private:
       MemoryBlock* pBlock;
       USHORT nUnitSize;
       USHORT nInitSize;
       USHORT nGrowSize;
       public:
       MemoryPool( USHORT nUnitSize,
       USHORT nInitSize = 1024,
       USHORT nGrowSize = 256 );
       ~MemoryPool();
       void* Alloc();
       void Free( void* p );
    };
    MemoryPool.cpp 的实现
    #include "MemoryPool.h"

    MemoryPool::MemoryPool( USHORT _nUnitSize,
    USHORT _nInitSize, USHORT _nGrowSize )
    {
      pBlock = NULL; 
      nInitSize = _nInitSize; 
      nGrowSize = _nGrowSize; 
      if ( _nUnitSize > 4 ) 

      nUnitSize = (_nUnitSize + (MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1); 
      else if ( _nUnitSize <= 2 )
      nUnitSize = 2; 
      else
      nUnitSize = 4;
    }

    void* MemoryPool::Alloc()
    {
      MemoryBlock* pMyBlock;
      if ( !pBlock ){
         //第一次调用初始化内存块
         pMyBlock =new(nGrowSize, nUnitSize) MemoryBlock(nGrowSize, nUnitSize);
         pBlock = pMyBlock;
          return (void*)(pMyBlock->aData);
      }
      pMyBlock = pBlock;
      while (pMyBlock && !pMyBlock->nFree )
        pMyBlock = pMyBlock->pNext;
      if ( pMyBlock ){
        printf("get a mem from block\n");
        char* pFree = pMyBlock->aData+(pMyBlock->nFirst*nUnitSize);
        //aData记录实际的内存单元标识
        pMyBlock->nFirst = *((USHORT*)pFree);
        pMyBlock->nFree--;
        return (void*)pFree;
      }
      else{
        printf("add a new block\n");
        if (!nGrowSize)
        return NULL;
        pMyBlock = new(nGrowSize, nUnitSize) MemoryBlock(nGrowSize, nUnitSize);
        if (!pMyBlock )
        return NULL;
        pMyBlock->pNext = pBlock;
        pBlock = pMyBlock;
        return (void*)(pMyBlock->aData);
      }
    }


    void MemoryPool::Free( void* pFree ){
      MemoryBlock* pMyBlock = pBlock;
      MemoryBlock* preMyBlock;
      //确定该待回收分配单元(pFree)落在哪一个内存块的指针范围内,大于起始节点,小于终止节点。
      while ( ((ULONG)pMyBlock->aData > (ULONG)pFree) ||
      ((ULONG)pFree >= ((ULONG)pMyBlock->aData + pMyBlock->nSize))){
        //不在内存块范围内,则历遍下一个节点
        preMyBlock=pMyBlock;
        pMyBlock=pMyBlock->pNext;
      }
      pMyBlock->nFree++; 
      *((USHORT*)pFree) = pMyBlock->nFirst; 
      pMyBlock->nFirst = (USHORT)(((ULONG)pFree-(ULONG)(pBlock->aData)) / nUnitSize);
      //判断内存块是否全部为自由状态,是则释放整个内存块
      if (pMyBlock->nFree*nUnitSize == pMyBlock->nSize ){
         preMyBlock->pNext=pMyBlock->pNext;
         delete pMyBlock;
      }
    }

    MemoryBlock::MemoryBlock (USHORT nTypes, USHORT nUnitSize)
    : nSize (nTypes * nUnitSize),
        nFree (nTypes - 1), 
      nFirst (1), 
      pNext (0)
    {
      char * pData = aData; 
      for (USHORT i = 1; i < nTypes; i++) {
        //将内存块的前2个字节用来存放内存单元的标识
        *reinterpret_cast<USHORT*>(pData) = i; 
        pData += nUnitSize;
      }
    }

    http://www.cnblogs.com/konyel/archive/2011/06/06/mempool.html

  • 相关阅读:
    百度脑图
    Bootstrap入门
    Tomcat热部署的三种方式
    There is a chart instance already initialized on the dom!警告
    Ubuntu14.04设置开机自启动脚本
    PRM路径规划算法
    A*算法
    V-rep学习笔记:串口操作
    V-rep学习笔记:机器人路径规划2
    V-rep学习笔记:机器人逆运动学解算
  • 原文地址:https://www.cnblogs.com/zzxap/p/2175669.html
Copyright © 2011-2022 走看看