在软件设计和开发过程中,合理高效的使用内存,关乎软件执行的效率和性能,内存管理至关重要,下面一种方法可以对分配的内存进行回收再利用,提高内存使用率,c++代码如下:
memmgr.h
#ifndef __MEMMGR_H
#define __MEMMGR_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include "commondatastruct.h"
using namespace std;
//define data type
enum MemoryType {B64_B,HALF_K,ONE_K,THREE_K,NO_MEM };
const int BaseBlkNum=1; //must be 1 for add free policy to OS when occupy to much .SRC is 20
const size_t B64 = 64;
const size_t HalfK = 1024;
const size_t OneK = 2048; //1024+ 512 = 1536
const size_t ThreeK = 3072; //1024*3
const size_t MaxSizeForListB64 = 10000; //6.4M
const size_t MaxSizeForListB1K = 10000; //20000K,20M
const size_t MaxSizeForListBHalfK = 10000; //10000K,10M
const size_t MaxSizeForListB3K = 5000; // 15000K,15M
class MemoryManager
{
public:
MemoryManager();
~MemoryManager();
void * Allocate(size_t len);
void Free(void *obj,size_t sz);
void OnTimer(time_t tm);
private:
void InitList(void * base,MemoryType mtype);
void CleanUp();
private:
list<void *> b64ptrlist_;
list<void *> b1kptrlist_;
list<void *> bhalf1kptrlist_;
list<void *> b3kptrlist_;
int newallocatecount_[THREE_K+1];
int reusedcount_[THREE_K+1];
int needcount_[THREE_K+1];
};
#endif
memmgr.cpp
#ifndef __MEMMGR_CPP
#define __MEMMGR_CPP
#include "memmgr.h"
using namespace std;
void MemoryManager::InitList(void * base,MemoryType mtype)
{
void *pbase = base;
int loop = 0;
if(B64_B==mtype)
{
//pbase+=64;
newallocatecount_[B64_B]++;
while(loop<=BaseBlkNum-1) { b64ptrlist_.push_back(pbase); /*pbase+=B64;*/loop++;}
}
else
if(HALF_K==mtype)
{
//pbase+=512;
newallocatecount_[HALF_K]++;
while(loop<=BaseBlkNum-1) { bhalf1kptrlist_.push_back(pbase); /*pbase+=HalfK;*/loop++;}
}
else
if(ONE_K == mtype)
{
//pbase+=1024;
newallocatecount_[ONE_K]++;
while(loop<=BaseBlkNum-1) { b1kptrlist_.push_back(pbase); /*pbase+=OneK;*/loop++;}
}
else
if(THREE_K == mtype)
{
//pbase+=3072;
newallocatecount_[THREE_K]++;
while(loop<=BaseBlkNum-1) { b3kptrlist_.push_back(pbase); /*pbase+=ThreeK*/;loop++;}
}
};
MemoryManager::MemoryManager()
{
Logging::Info("[%d],%s,{%10u},Now MemoryManager creating ....\n",__LINE__,FileNameFormat(__FILE__),pThread_Self());
for(int i=0;i<=THREE_K;i++)
{
newallocatecount_[i]=0;
reusedcount_[i]=0;
needcount_[i]=0;
}
}
MemoryManager::~MemoryManager()
{
//CleanUp();
void *pbase = NULL;
//B64
list<void *>::iterator it64 = b64ptrlist_.begin();
while(it64 != b64ptrlist_.end())
{
pbase = (*it64);
free(pbase);
pbase = NULL;
it64++;
}
b64ptrlist_.clear();
//B1K
list<void *>::iterator it1k = b1kptrlist_.begin();
while(it1k !=b1kptrlist_.end())
{
pbase =(*it1k);
free(pbase);
pbase = NULL;
it1k++;
}
b1kptrlist_.clear();
//BHalfK
list<void *>::iterator ithalfk = bhalf1kptrlist_.begin();
while(ithalfk != bhalf1kptrlist_.end())
{
pbase = (*ithalfk);
free(pbase);
pbase = NULL;
ithalfk++;
}
bhalf1kptrlist_.clear();
//B3K
list<void *>::iterator it3k = b3kptrlist_.begin();
while(it3k != b3kptrlist_.end())
{
pbase = (*it3k);
free(pbase);
pbase = NULL;
it3k++;
}
b3kptrlist_.clear();
Logging::Info("[%d],%s,{%10u},MemoryManager destroy ......\n",__LINE__,FileNameFormat(__FILE__),pThread_Self());
}
void * MemoryManager::Allocate(size_t len)
{
void *base=0;
void * blockptr=NULL;
MemoryType mtype = NO_MEM;
if(len< B64)
mtype = B64_B;
else
if(len < HalfK)
mtype = HALF_K;
else
if(len < OneK)
mtype = ONE_K;
else
if(len < ThreeK)
mtype = THREE_K;
switch (mtype)
{
case B64_B:
{
if(b64ptrlist_.empty())
{
base = malloc(B64 * BaseBlkNum);
if(base==NULL)
{
//TraceAndAlarm cout<<"NOT enough memory to allocate"<<endl;
return NULL;
}
else
{
memset(base,0,B64*BaseBlkNum);
needcount_[B64_B]++;
newallocatecount_[B64_B]++;
return base;
}
}
else
{
blockptr = b64ptrlist_.front();
b64ptrlist_.pop_front();
needcount_[B64_B]++;
return blockptr;
}
break;
}
case HALF_K:
{
if(bhalf1kptrlist_.empty())
{
base = malloc(HalfK * BaseBlkNum);
if(base==NULL)
{
//TraceAndAlarm cout<<"NOT enough memory to allocate"<<endl;
return NULL;
}
else
{
memset(base,0,HalfK*BaseBlkNum);
needcount_[HALF_K]++;
newallocatecount_[HALF_K]++;
return base;
}
}
else
{
blockptr = bhalf1kptrlist_.front();
bhalf1kptrlist_.pop_front();
needcount_[HALF_K]++;
return blockptr;
}
break;
}
case ONE_K:
{
if(b1kptrlist_.empty())
{
base = malloc(OneK * BaseBlkNum);
if(base==NULL)
{
//Logging::Info("[%d],%s,{%10u},MemoryManager Allocate OneK failed \n",__LINE__,FileNameFormat(__FILE__),pThread_Self());
return NULL;
}
else
{
memset(base,0,OneK*BaseBlkNum);
needcount_[ONE_K]++;
newallocatecount_[ONE_K]++;
return base;
}
}
else
{
blockptr = b1kptrlist_.front();
b1kptrlist_.pop_front();
needcount_[ONE_K]++;
return blockptr;
}
break;
}
case THREE_K:
{
if(b3kptrlist_.empty())
{
base = malloc(ThreeK * BaseBlkNum);
if(base==NULL)
{
return NULL;
}
else
{
memset(base,0,ThreeK*BaseBlkNum);
needcount_[THREE_K]++;
newallocatecount_[THREE_K]++;
return base;
}
}
else
{
blockptr = b3kptrlist_.front();
b3kptrlist_.pop_front();
needcount_[THREE_K]++;
return blockptr;
}
break;
}
default:
return NULL;
}
return NULL;
/* if(len<=B64) //block 64
{
if(b64ptrlist_.empty())
{
//base = new char[B64 * BaseBlkNum];
base = malloc(B64 * BaseBlkNum);
if(base==NULL)
{
//TraceAndAlarm cout<<"NOT enough memory to allocate"<<endl;
return 0;
}
else
{
memset(base,0,B64*BaseBlkNum);
//mempoollist_.push_back(base);
InitList(base,B64_B);
}
blockptr = b64ptrlist_.front();
b64ptrlist_.pop_front();
needcount_[B64_B]++;
return blockptr;
}
else
{
blockptr = b64ptrlist_.front();
b64ptrlist_.pop_front();
needcount_[B64_B]++;
return blockptr;
}
}
else
if(len<=HalfK) //block 512
{
if(bhalf1kptrlist_.empty())
{
//base = new char[HalfK * BaseBlkNum];
base = malloc(HalfK * BaseBlkNum);
if(base==NULL)
{
//TraceAndAlarm cout<<"NOT enough memory to allocate"<<endl;
return 0;
}
else
{
memset(base,0,HalfK*BaseBlkNum);
//mempoollist_.push_back(base);
InitList(base,HALF_K);
}
blockptr = bhalf1kptrlist_.front();
bhalf1kptrlist_.pop_front();
needcount_[HALF_K]++;
return blockptr;
}
else
{
blockptr = bhalf1kptrlist_.front();
bhalf1kptrlist_.pop_front();
needcount_[HALF_K]++;
return blockptr;
}
}
else
if(len <=OneK) //block 1500
{
if(b1kptrlist_.empty())
{
//base = new char[OneK * BaseBlkNum];
base = malloc(OneK * BaseBlkNum);
if(base==NULL)
{
//TraceAndAlarm cout<<"NOT enough memory to allocate"<<endl;
Logging::Info("[%d],%s,{%10u},MemoryManager Allocate OneK failed \n",__LINE__,FileNameFormat(__FILE__),pThread_Self());
return NULL;
}
else
{
memset(base,0,OneK*BaseBlkNum);
//mempoollist_.push_back(base);
InitList(base,ONE_K);
}
blockptr = b1kptrlist_.front();
b1kptrlist_.pop_front();
needcount_[ONE_K]++;
return blockptr;
}
else
{
blockptr = b1kptrlist_.front();
b1kptrlist_.pop_front();
needcount_[ONE_K]++;
return blockptr;
}
}
else
if(len <=ThreeK) //block 3072
{
if(b3kptrlist_.empty())
{
//base = new char[ThreeK * BaseBlkNum];
base = malloc(ThreeK * BaseBlkNum);
if(base==NULL)
{
//TraceAndAlarm cout<<"NOT enough memory to allocate"<<endl;
return 0;
}
else
{
memset(base,0,ThreeK*BaseBlkNum);
//mempoollist_.push_back(base);
InitList(base,THREE_K);
}
blockptr = b3kptrlist_.front();
b3kptrlist_.pop_front();
needcount_[THREE_K]++;
return blockptr;
}
else
{
blockptr = b3kptrlist_.front();
b3kptrlist_.pop_front();
needcount_[THREE_K]++;
return blockptr;
}
}
return 0;
*/
};
void MemoryManager::Free(void *obj,size_t sz)
{
MemoryType mtype=NO_MEM;
if(sz<B64)
mtype = B64_B;
else
if(sz<HalfK)
mtype = HALF_K;
else
if(sz<OneK)
mtype = ONE_K;
else
if(sz < ThreeK)
mtype = THREE_K;
//statistic reuse memory
reusedcount_[mtype]++;
switch (mtype)
{
case B64_B:
memset(obj,0,B64);
b64ptrlist_.push_front(obj);
return;
case HALF_K:
memset(obj,0,HalfK);
bhalf1kptrlist_.push_front(obj);
return;
case ONE_K:
memset(obj,0,OneK);
b1kptrlist_.push_front(obj);
return;
case THREE_K:
memset(obj,0,ThreeK);
b3kptrlist_.push_front(obj);
return;
default:
free(obj);
obj = NULL;
return;
}
};
void MemoryManager::CleanUp()
{
};
void MemoryManager::OnTimer(time_t tm)
{
Logging::Info("{%10u},Mem Usage Info: B64 [size: %u,NC: %u, RU: %u, ND: %u], B1k [size: %u,NC: %u, RU: %u, ND: %u], BhalfK [size: %u,NC: %u, RU: %u,ND: %u], B3K [size: %u,NC: %u, RU: %u, ND: %u] \n",pThread_Self(),b64ptrlist_.size(),newallocatecount_[B64_B]*BaseBlkNum,reusedcount_[B64_B],needcount_[B64_B],b1kptrlist_.size(),newallocatecount_[ONE_K]*BaseBlkNum,reusedcount_[ONE_K],needcount_[ONE_K],bhalf1kptrlist_.size(),newallocatecount_[HALF_K]*BaseBlkNum,reusedcount_[HALF_K],needcount_[HALF_K],b3kptrlist_.size(),newallocatecount_[THREE_K]*BaseBlkNum,reusedcount_[THREE_K],needcount_[THREE_K]);
for(int i=0;i<=THREE_K;i++)
{
newallocatecount_[i]=0;
reusedcount_[i]=0;
needcount_[i]=0;
}
//check if need to free some memory to OS
size_t tmplistlen = b64ptrlist_.size();
//B64
if(tmplistlen > MaxSizeForListB64 *2)
{
size_t tmplen = tmplistlen - MaxSizeForListB64;
void *pbase = NULL;
while(tmplen > 1)
{
pbase = b64ptrlist_.front();
b64ptrlist_.pop_front();
free(pbase);
pbase = NULL;
tmplen--;
}
}
//B1K
tmplistlen = b1kptrlist_.size();
if( tmplistlen> MaxSizeForListB1K *2)
{
size_t tmplen = tmplistlen - MaxSizeForListB1K;
void *pbase = NULL;
while(tmplen > 1 )
{
pbase = b1kptrlist_.front();
b1kptrlist_.pop_front();
if(pbase !=NULL)
{
free(pbase);
pbase = NULL;
}
tmplen--;
}
}
//BHalfK
tmplistlen = bhalf1kptrlist_.size();
if(tmplistlen > MaxSizeForListBHalfK *2)
{
size_t tmplen = tmplistlen - MaxSizeForListBHalfK;
void *pbase = NULL;
while(tmplen > 1)
{
pbase = bhalf1kptrlist_.front();
bhalf1kptrlist_.pop_front();
free(pbase);
pbase = NULL;
tmplen--;
}
}
//B3K
tmplistlen = b3kptrlist_.size();
if(tmplistlen > MaxSizeForListB3K *2)
{
size_t tmplen = tmplistlen - MaxSizeForListB3K;
void *pbase = NULL;
while(tmplen > 1)
{
pbase = b3kptrlist_.front();
b3kptrlist_.pop_front();
free(pbase);
pbase = NULL;
tmplen--;
}
}
}
#endif