自适配型内存池

版权声明:本文为博主原创文章,未经博主允许不得转载。

互联网技术中 使用内存池已是必不可少的,内存池节省了 大块内存不断new导致的并发瓶颈,但是内存池的大小成了问题,初始分的时候要分配一大批内存进来,如果程序并发量少则将在很长一段时间内,这段内存耗着没用,这是一种资源的浪费,所以本文本着,可变内存池的思想去设计动态内存池类,内存池从1到最大值慢慢涨进,同时用过的内存闲置后,新内存请求先使用回收池中的内存池,如果不够,才去申请新的内存。

数据 图示如下:

 

不会多啰嗦直接见代码

这里写测试代码片
``
struct VIEW_DATA
{
    longlong lWith;
    longlong lHeath;
    longlong lYManager;
    longlong ParamReserver;
};`
int _tmain(int argc, _TCHAR* argv[])
{
    CAcummultMemPool<VIEW_DATA> MemBuf;

    VIEW_DATA *pBufData=MemBuf.NewData();
    //泰山鲁言 请君随意使用,内存已经被分出来了,使用完记着回收就可以了
    pBufData->lWith=22222;
    pBufData->lYManager=7777;
    //之后随你拿别的线程用,我就省略了懒得啰嗦//................//用完了收起来
    MemBuf.FreeData(pBufData);

    //一定要记清楚,否则内存泄露泰山鲁不负责任
    MemBuf.ClearPool();
    return0;
}

内存池代码这里写代码片
#
include <windows.h> 
struct STURCT_NODE
{
    int iIndexReserve;
    void * m_pData;
    //基本数据结构这个不用解释太多
    STURCT_NODE * m_pNext;
};
template <class DataType>
class CAcummulteQue
{
    CAcummulteQue()
    {
        m_pHead = NULL;
        m_nBufNum = 0;
        m_nMaxDataSize = 1000;//小于1000的池new就行了,用哥的这套缓存池这么折腾就是给自己找麻烦
        m_pTail = NULL;
        m_pRecoverDataList = NULL;
        InitializeCriticalSection(&m_oLock); 

        //开始先分他一批出来多少你自己定//......
    };

    //删除所有的节点和回收节点不论在回收区还是再node区间
    ~CAcummulteQue()
    {
        STURCT_NODE * lpNode = NULL;
        while (m_pHead)
        {
            lpNode = m_pHead->m_pNext;
            delete (DataType *)m_pHead->m_pData;
            delete m_pHead;
            m_pHead = lpNode;
        }

        while (m_pRecoverDataList)
        {
            lpNode = m_pRecoverDataList->m_pNext;
            delete m_pRecoverDataList;
            m_pRecoverDataList = lpNode;
        }
        m_nBufNum = 0;
    };
private:
    STURCT_NODE *   m_pRecoverDataList;
    int                 m_nNodeNum;
    CRITICAL_SECTION    m_oLock;
    int                 m_nBufNum;
    int                 m_nMaxDataSize;

    //节点链表
    STURCT_NODE *   m_pHead;
    STURCT_NODE *   m_pTail;

public:
     void SetCacheSize(int nCacheSize)
    {
        m_nMaxDataSize = nCacheSize;
    };

public:
    //从node池中找到一个之后,找到后供写,录在list上供回收使用
     DataType * GetBuffer()
    {
        DataType * pValue = NULL;
          EnterCriticalSection(&m_oLock);
        if (m_pHead != NULL)//存在则拉一个节点出来供使用
        {
            pValue = (DataType *)m_pHead->m_pData;
            STURCT_NODE * lpNode = m_pHead->m_pNext;
            AddNodeToList(m_pHead);
            m_pHead = lpNode;
            if (m_pHead == NULL)
                m_pTail = NULL;
        }
        else
        {
            pValue = NULL;
        }
          LeaveCriticalSection(&m_oLock);
        if (NULL == pValue) {
            returnNULL;
        }

        return pValue;
    };

     //注意是节点本身,注意不是增加内存而是增加节点自己本身,//节点上放指向内存空间的指针地址,此处只是增加节点,不是增加内存int AddNodeToSaveData(DataType * apMemValue)
     {
         int nNodeCount = 0;
          EnterCriticalSection(&m_oLock);
         //从回收list中从头部找第一个node,有了揪出来用,没的话分配一个节点出来供使用
         STURCT_NODE * lpNode = NewNodeRecoverList();
         lpNode->m_pNext = NULL;
         lpNode->m_pData = apMemValue;
         if (m_pTail != NULL)
         {
             m_pTail->m_pNext = lpNode;
             m_pTail = lpNode;
         }
         else
         {
             m_pHead = lpNode;
             m_pTail = lpNode;
         }
         m_nNodeNum ++;
         nNodeCount = m_nNodeNum;
         EnterCriticalSection(&m_oLock);
         return nNodeCount;
     };


     //回收list中取出一个或者增加一个节点
     STURCT_NODE * NewNodeRecoverList()
     {
         //注意new的是一个node,就是node链表的长度而不是数据本身if (m_pRecoverDataList)
         {
             STURCT_NODE * lpNode = m_pRecoverDataList;
             m_pRecoverDataList = m_pRecoverDataList->m_pNext;
             m_nBufNum--;
             return lpNode;
         }
         else
         {
             //std::nothrow目的是内存不足时不返回NULLreturn new (std::nothrow) STURCT_NODE;
         }
     };

     //向list续点节点,只添加不生成void AddNodeToList(STURCT_NODE *& pNode)
     {
         if (pNode)
         {
             if (m_nBufNum < m_nMaxDataSize)
             {
                 pNode->m_pNext = m_pRecoverDataList;
                 m_pRecoverDataList = pNode;
                 m_nBufNum ++;
             }
             else
             {
                 delete pNode;
             }
             pNode = NULL;
         }
     };

     void Clear()
    {
        STURCT_NODE * lpNode = NULL;
        m_oLock.Lock();
        while (m_pHead)
        {
            lpNode = m_pHead->m_pNext;
            delete (DataType *)m_pHead->m_pData;
            AddNodeToList(m_pHead);
            m_pHead = lpNode;
            if (m_pHead == NULL)
                m_pTail = NULL;
        }
        m_nNodeNum = 0;
        m_oLock.UnLock();
    };
     void RemoveAll()
    {
        STURCT_NODE * lpNode = NULL;
        m_oLock.Lock();
        while (m_pHead)
        {
            lpNode = m_pHead->m_pNext;
            AddNodeToList(m_pHead);
            m_pHead = lpNode;
            if (m_pHead == NULL)
                m_pTail = NULL;
        }
        m_oLock.UnLock();
    };


};

//外层使用类
189


这里写代码片 
“` 
ifndef ACUMULTEMEMPOOL_LU 
define ACUMULTEMEMPOOL_LU 
include “CAcummulteQue.h” 
include 
template 
class CAcummultMemPool 
{ 
public: 
CAcummultMemPool(); 
~CAcummultMemPool(); 
private: 
CAcummulteQue m_oMemPool; 
CRITICAL_SECTION m_hSignal; 
long m_lCreateCount;
public: 
//三个内存分配函数 
DType * NewData(); 
void FreeData(DType * a_pObjet); 
void ClearPool();
};
template 
DType * CAcummultMemPool::NewData() 
{ 
DType * pObj = NULL; 
pObj = m_oMemPool.GetBuffer(); 
if (pObj) 
{ 
return pObj; 
}
//这个地方有待进一步改进,模块化的类突然来个new
pObj = new (std::nothrow) DType;
if (pObj)
{
     EnterCriticalSection(&m_hSignal);
     m_lCreateCount ++;
     LeaveCriticalSection(&m_hSignal); 
}

return pObj;
}


这个算法的研究:

就如图锁说明,来一个分配在上面的node中,被取出来用完之后,再回收到回收池中,有新的请求再来就不必new直接使用刚用完后的内存,缓存空间一直是涨的趋势,最终缓存需要多少由系统需求来决定,读者可以自己设个最大数值,防止这个程序占了太多的内存。还有一处需要优化之处是,一个程序初始的时候一定会使用多少的内存,大概是有个数的,就是内存池初始的时候应该预留点空间出来,在不够用的使用才去新分配池,读者可以自己重写这个类。 
版权所有,转载著名明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值