问题描述:
1.利用STL vector维护不同的多个定长单元的内存块;
2.当内存池外部申请内存是,利用STL vector at 接口和有效内存索引高效返回所需内存,然后增加有效内存索引到下一个;
3.当外部交还内存到池子时,交换这个有效内存到当前无效的内存块位置,并缩减有效内存索引;
4.如此复杂的操作是问了保证内存池的性能;
程序代码:
#ifndef _MEMORY_BLOCK_POOL_H_
#define _MEMORY_BLOCK_POOL_H_
#include <stdlib.h>
#include <vector>
#include "windows.h"
#define ALIGN( size, bits ) ( ( ( ( size - 1 ) >> bits ) + 1 ) << bits )
/*
* memory pool fixed length block
*
*
*/
class MemoryBlockPool
{
public:
static const int MAXBLOCK = 256;
static const int MALLOCKSIZE = 4096;
static const int DEFAULTBASELEN = 4;
typedef struct tagMemStatInfo
{
char* allocMem;
size_t allocSize;
tagMemStatInfo():allocMem(0),allocSize(0)
{
}
tagMemStatInfo( char* mem, size_t size ):allocMem(mem),
allocSize(size)
{
}
}MemStatInfo, *pMemStatInfo;
typedef struct tagMemoryBlock
{
std::vector<char*> Block;
size_t validIdx;
tagMemoryBlock():Block(), validIdx(0)
{
}
}MemoryBlock, *pMemoryBlock;
typedef std::vector<char*> BlockContainer;
/*
*
*
*/
MemoryBlockPool( size_t baseLen = DEFAULTBASELEN ):m_pool(0),
m_poolSize(0), m_baseLen(baseLen),
m_memStat()
{
Init( m_baseLen );
}
/*
*
*
*/
~MemoryBlockPool()
{
Release();
}
/*
* Release all memory allocated
*
*/
void Release()
{
std::vector<MemStatInfo>::iterator iter = m_memStat.begin();
while( iter != m_memStat.end() )
{
free( iter->allocMem );
++iter;
}
for( size_t i = 0; i < m_poolSize; i++ )
{
m_pool[i].Block.clear();
}
}
/*
* get memory for given length from cahce array or os
*
*/
void* Malloc( size_t len )
{
assert( len > 0 );
size_t size = ALIGN( len, 2 );
if( size > MAXBLOCK )
{
return malloc(size);
}
if( !m_pool[size].Block.size() )
{
size_t memLen = size + 4;
char* buf = (char*)malloc( MALLOCKSIZE );
size_t blockNums = MALLOCKSIZE / memLen;
BlockContainer& container = m_pool[size].Block;
container.reserve( blockNums );
for( size_t i = 0; i < blockNums; i++ )
{
*(buf + i * size) = i;
container.push_back( buf + i * size );
}
m_memStat.push_back( MemStatInfo( buf, MALLOCKSIZE ) );
}
else if( m_pool[size].validIdx == m_pool[size].Block.size() )
{
size_t memLen = size + 4;
char* buf = (char*)malloc( MALLOCKSIZE );
size_t blockNums = MALLOCKSIZE / memLen;
BlockContainer& container = m_pool[size].Block;
for( size_t i = 0; i < blockNums; i++ )
{
*(int*)(buf + i * size) = i + container.size();
container.push_back( buf + i * size );
}
}
char* buf = m_pool[size].Block.at( m_pool[size].validIdx );
m_pool[size].validIdx++;
return buf + 4;
}
/*
* give back memory to cache or os
*
*/
void Free( void* mem, size_t len )
{
assert( len > 0 );
size_t size = ALIGN( len, 2 );
if( size > MAXBLOCK )
{
return free( mem );
}
char* buf = (char*)mem;
buf -= 4;
if( m_pool[size].validIdx )
{
Swap( m_pool[size].Block.at( m_pool[size].validIdx - 1), buf );
m_pool[size].validIdx--;
}
}
private:
void Swap( char*& bufFirst, char*& bufSecond )
{
char* temp = bufFirst;
bufFirst = bufSecond;
bufSecond = temp;
}
/*
*
*
*/
void Init( size_t baseLen )
{
m_poolSize = MAXBLOCK / baseLen;
m_pool = new MemoryBlock[m_poolSize];
}
private:
MemoryBlock *m_pool; // memory block array
size_t m_poolSize; // the size of memory block array
size_t m_baseLen; //
std::vector<MemStatInfo> m_memStat;
};
//test object one
typedef struct tagTestObjFirst
{
int first;
int second;
tagTestObjFirst():first(0), second(0)
{
}
tagTestObjFirst( int i, int j ):first(i), second(j)
{
}
}TestObjFirst, *pTestObjFrist;
// test object two
typedef struct tagTestObjSecond
{
int first;
int second;
std::string name;
tagTestObjSecond():first(0), second(0)
{
}
tagTestObjSecond( int i, int j, const char* str ):first(i), second(j), name( str )
{
}
}TestObjSecond, *pTestObjSecond;
/*
* Test os memory operation
*
*/
void BlockTestOSMemory()
{
unsigned long start = GetTickCount();
const int len = 2000000;
int halfLen = len / 2;
pTestObjFrist* objs = new pTestObjFrist[len];
pTestObjSecond* objExts = new pTestObjSecond[len];
for( int i = 0; i < len; i++ )
{
objs[i] = new TestObjFirst( i, i );
objExts[i] = new TestObjSecond( i, i, "test" );
delete objs[i];
delete objExts[i];
}
unsigned long interval = GetTickCount() - start;
printf(" system call consume time %d for memory operation \n", interval );
delete [] objs;
delete [] objExts;
}
/*
*Test memory pool
*
*
*/
void BlockTestMemoryBlock()
{
unsigned long start = GetTickCount();
const int len = 2000000;
int halfLen = len / 2;
MemoryBlockPool memPool;
pTestObjFrist* objs = new pTestObjFrist[len];
pTestObjSecond* objExts = new pTestObjSecond[len];
for( int i = 0; i < len; i++ )
{
void* buf = memPool.Malloc( sizeof(TestObjFirst) );
objs[i] = new (buf) TestObjFirst( i, i );
buf = memPool.Malloc( sizeof(TestObjSecond) );
objExts[i] = new (buf) TestObjSecond( i, i, "test" );
memPool.Free( buf, sizeof(TestObjFirst) );
memPool.Free( buf, sizeof(TestObjSecond) );
}
unsigned long interval = GetTickCount() - start;
printf(" memory pool call consume time %d for memory operation \n", interval );
delete [] objs;
delete [] objExts;
}
/*
*Test interface for memory operation
*
*
*/
void TestSuiteCacheBlock()
{
BlockTestMemoryBlock();
BlockTestOSMemory();
}
#endif
compile and run in visual studio 2005