首页 > 代码库 > 定长单元的批次内存缓存池的简洁实现
定长单元的批次内存缓存池的简洁实现
问题描述:
1.内存管理计算机编程中一个基本问题,其目的在于:
1)一次可分配多个单元块,缓存维护,以改善反复的小对象申请的性能开销;
2) 管理以分配的内存,有效减少碎片的产生;
3) 保证软件使用的内存透明,了解峰值,了解使用情况,便于优化查错;
2.常用的内存管理机制有以下:
1) 变长块,依靠链表维护,一个节点一块申请了的内存,内存块大小不等,等接到一个申请时,先查维护的链表,若有可从链表取出。这种方法有很多缺点:1,当申请的内存块要遍历链表节点找到大小合适的块,最坏情况下需要把链表所有节点遍历一遍,2.造成浪费,当从链表拿到块的大小远大于所需时,造成浪费;
2)定长单元,系统维护一个内存链表的数组,数组每项对应一个等长的多个内存单元,一次分配好。当申请到来时, 先根据申请尺寸确定对应的数组项,然后从链表头上返回所需内存节点,归还时可加尾部或者头部;
3.本文按定长单元的思想实现,实现方法由于利用了STL vector数组充当内存维护所需的链表数组,所以程序实现很简洁;
4. 本文内存池接口和系统内存操作接口做了性能上的比较;
程序代码:
#ifndef _MEMORY_BLOCK_CACHE_H_ #define _MEMORY_BLOCK_CACHE_H_ #include <stdlib.h> #include <vector> #include "windows.h" #define ALIGN( size, bits ) ( ( ( ( size - 1 ) >> bits ) + 1 ) << bits ) /* * memory pool fixed length block * * */ class MemoryBlockCache { 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; /* * * */ MemoryBlockCache( size_t baseLen = DEFAULTBASELEN ):m_pool(0), m_poolSize(0), m_baseLen(baseLen), m_memStat() { Init( m_baseLen ); } /* * * */ ~MemoryBlockCache() { 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].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].size() ) { char* buf = (char*)malloc( MALLOCKSIZE ); size_t blockNums = MALLOCKSIZE / size; m_pool[size].reserve( blockNums ); for( size_t i = 0; i < blockNums; i++ ) { m_pool[size].push_back( buf + i * size ); } m_memStat.push_back( MemStatInfo( buf, MALLOCKSIZE ) ); } char* res = m_pool[size].back(); m_pool[size].pop_back(); return res; } /* * 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 ); } m_pool[size].push_back( (char*)mem ); } private: /* * * */ void Init( size_t baseLen ) { m_poolSize = MAXBLOCK / baseLen; m_pool = new std::vector<char*>[m_poolSize]; } private: std::vector<char*> *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 tagBlockTestObj { int first; int second; tagBlockTestObj():first(0), second(0) { } tagBlockTestObj( int i, int j ):first(i), second(j) { } }BlockTestObj, *pBlockTestObj; // test object two typedef struct tagBlockTestExtObj { int first; int second; std::string name; tagBlockTestExtObj():first(0), second(0) { } tagBlockTestExtObj( int i, int j, const char* str ):first(i), second(j), name( str ) { } }BlockTestExtObj, *pBlockTestExtObj; /* * Test os memory operation * */ void TestOSMemory() { unsigned long start = GetTickCount(); const int len = 2000000; int halfLen = len / 2; pBlockTestObj* objs = new pBlockTestObj[len]; pBlockTestExtObj* objExts = new pBlockTestExtObj[len]; for( int i = 0; i < len; i++ ) { objs[i] = new BlockTestObj( i, i ); objExts[i] = new BlockTestExtObj( 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 TestMemoryBlock() { unsigned long start = GetTickCount(); const int len = 2000000; int halfLen = len / 2; MemoryBlockCache memPool; pBlockTestObj* objs = new pBlockTestObj[len]; pBlockTestExtObj* objExts = new pBlockTestExtObj[len]; for( int i = 0; i < len; i++ ) { void* buf = memPool.Malloc( sizeof(BlockTestObj) ); objs[i] = new (buf) BlockTestObj( i, i ); buf = memPool.Malloc( sizeof(BlockTestExtObj) ); objExts[i] = new (buf) BlockTestExtObj( i, i, "test" ); memPool.Free( buf, sizeof(BlockTestObj) ); memPool.Free( buf, sizeof(BlockTestExtObj) ); } 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 TestSuiteMemoryBlock() { TestMemoryBlock(); TestOSMemory(); } #endif
compile and run in visual studio 2005
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。