版权声明:本文为博主原创文章,未经博主允许不得转载。
互联网技术中 使用内存池已是必不可少的,内存池节省了 大块内存不断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直接使用刚用完后的内存,缓存空间一直是涨的趋势,最终缓存需要多少由系统需求来决定,读者可以自己设个最大数值,防止这个程序占了太多的内存。还有一处需要优化之处是,一个程序初始的时候一定会使用多少的内存,大概是有个数的,就是内存池初始的时候应该预留点空间出来,在不够用的使用才去新分配池,读者可以自己重写这个类。
版权所有,转载著名明出处。