首页 > 代码库 > 一个利用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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。