為了提高效率和有效的監控記憶體的實時狀态,我們采取了記憶體池的思想來解決效率與對記憶體實作監控的問題。
網上查找到了一些方案,根據自己的了解實作了應用。
我們什麼時候要調用到記憶體池,
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 )
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;