您的位置:首页 > 编程语言

内存池完整实现代码及一些思考

2011-06-06 15:41 435 查看
为了提高效率和有效的监控内存的实时状态,我们采取了内存池的思想来解决效率与对内存实现监控的问题。

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

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

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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: