我做了一个小机制来取代常规的new运算符。 基本上我们分配一个内存池(如16mb),当调用new时,返回 它的偏移量增长,直到没有更多的空间,我们再建一个池。一个游泳池 仅在释放该池中的所有元素时删除。
我已经测试了这个类,它的效果很好,比原来的新版快了大约8-15倍。 但是有一个问题:我将它合并到我的其他项目中,这个项目规模巨大 除了内存使用量增长非常快之外,它们正常工基本上没有释放池,因为 其中的一些项目根本不会被删除。此外,还有许多来自STL容器的new(0)调用 我不知道应该怎么回应。
以下是代码:
namespace rt
{
class pool
{
friend class alloc;
private:
unsigned int _numRecords;
unsigned int _sizeLeft;
char* _ptr;
char* _data;
};
class alloc
{
public:
alloc();
alloc(int mb);
~alloc();
void* allocate(unsigned int size);
void constructPool(unsigned int idx);
void destroyPool(unsigned int idx);
void deallocate(void* ptr);
private:
const static unsigned int _numPools = 256;
const static unsigned int _poolSize = 15*1024*1024;
const static unsigned int _poolReplaceBound = 1*1024*1024; // if 1mb or less left we can replace it
pool* _pools[_numPools];
unsigned int _curPoolIdx;
};
这就是标题。 以下是实施:
namespace rt
{
class pool
{
friend class alloc;
private:
unsigned int _numRecords;
unsigned int _sizeLeft;
char* _ptr;
char* _data;
};
class alloc
{
public:
alloc();
alloc(int mb);
~alloc();
void* allocate(unsigned int size);
void constructPool(unsigned int idx);
void destroyPool(unsigned int idx);
void deallocate(void* ptr);
private:
const static unsigned int _numPools = 256;
const static unsigned int _poolSize = 15*1024*1024;
const static unsigned int _poolReplaceBound = 1*1024*1024; // if 1mb or less left we can replace it
pool* _pools[_numPools];
unsigned int _curPoolIdx;
};
extern alloc default_allocator;
}
#define RT_SAFE_MEM
namespace rt
{
alloc default_allocator;
alloc::alloc()
{
for(int i = 0; i < _numPools; i++) _pools[i] = NULL;
_curPoolIdx = 0;
constructPool(_curPoolIdx);
}
alloc::~alloc()
{
}
void alloc::constructPool(unsigned int idx)
{
_pools[idx] = (pool*)malloc(sizeof(pool));
_pools[idx]->_numRecords = 0;
_pools[idx]->_sizeLeft = _poolSize;
_pools[idx]->_data = (char*)calloc(_poolSize, 1);
_pools[idx]->_ptr = _pools[idx]->_data;
}
void alloc::destroyPool(unsigned int idx)
{
free(_pools[idx]->_data);
free(_pools[idx]);
_pools[idx] = NULL;
}
void* alloc::allocate(unsigned int size)
{
if(size == 0)
{
return NULL;
}
#ifdef RT_SAFE_MEM
if(size > _poolSize)
{
MessageBox(NULL, "Allocation size exceeded maximum.", "Executor", MB_OK);
return NULL;
}
if(*(_pools[_curPoolIdx]->_ptr) != 0)
{
//leak
unsigned int leaksize = strlen(_pools[_curPoolIdx]->_ptr);
char str[50];
sprintf(str, "Memory corruption detected: wrote extra %u bytes. \nExporting to corrupt.txt", leaksize);
FILE* fp = fopen("corrupt.txt", "w");
fwrite(_pools[_curPoolIdx]->_ptr, 1, leaksize, fp);
fclose(fp);
MessageBox(NULL, str, "Executor", MB_OK);
return NULL;
}
#endif
if(_pools[_curPoolIdx]->_sizeLeft <= size)
{
//not enough size in this pool
//make a new one
_curPoolIdx++;
//printf("expand");
constructPool(_curPoolIdx);
return allocate(size);
}
else
{
void* ans = (void*)_pools[_curPoolIdx]->_ptr;
_pools[_curPoolIdx]->_ptr+=size;
_pools[_curPoolIdx]->_sizeLeft-=size;
_pools[_curPoolIdx]->_numRecords++;
return ans;
}
}
void alloc::deallocate(void* ptr)
{
for(int i = 0; i <= _curPoolIdx; i++)
{
if(ptr >= _pools[i]->_data && ptr < _pools[i]->_ptr)
{
//pool i contains this object
//printf("found %d\n", i);
_pools[i]->_numRecords--;
if(_pools[i]->_numRecords == 0 && _pools[i]->_sizeLeft <= _poolReplaceBound)
{
//replace this pool
printf("replacing %d\n", i);
destroyPool(i);
if(_curPoolIdx == 0) constructPool(0);
else
{
for(int j = i; j < _numPools-1; j++)
{
_pools[j] = _pools[j+1];
}
_curPoolIdx--;
}
}
return;
}
}
#ifdef RT_SAFE_MEM
char str[50];
sprintf(str, "Attempted to deallocate foreign memory at 0x%.8X.", ptr);
MessageBox(NULL, str, "Executor", MB_OK);
#endif
}
}
如果有人看到错误或重大问题,请告诉我。 谢谢!
答案 0 :(得分:2)
我建议您执行所有以下步骤: