首页 > 代码库 > 一个利用memory block分配机制的高性能的内存管理器类

一个利用memory block分配机制的高性能的内存管理器类

问题描述:

1.众所周知,内存管理机制几乎存在于一切优秀的系统中。这样做原因不外乎以下几点:1.改善性能;2.减少碎片的产生;3.侦测系统的内存使用情况,便于调错,便于了解系统的内存使用,以对系统的架构从内存使用层面上进行设计考量;

2.我前面有文已经说明,内存管理的机制一般分为:1.预先分配大量等尺寸的块,自己维护,逐次满足对单个内存单元的请求;2.释放的内存也自己维护,以便重复使用;3.使用定长和变长机制进行内存管理。

3.本文试着以较大尺寸(4096)的内存块为分配单元,然后在一个块中利用指针偏移来满足小对象的内存申请,当当前块内存耗尽时,又分配同样尺寸的内存块,重复以前工作。块与块之间靠指针维护(next)。

4.程序交还的内存,以内存尺寸为键,存入STL map;

5.当STL map中有内存时,优先从此中寻找满足的给定尺寸的内存需求;

6.和直接系统申请内存对比测试,发现,执行相同的操作,本内存管理器所消耗时间仅为系统内存申请耗时的十分之一


程序代码:

#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