定长单元的批次内存缓存池的简洁实现
来源:互联网 发布:闲鱼交易网络课程账号 编辑:程序博客网 时间:2024/06/05 23:54
问题描述:
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 arraysize_t m_poolSize; // the size of memory block arraysize_t m_baseLen; // std::vector<MemStatInfo> m_memStat;};//test object onetypedef struct tagBlockTestObj{int first;int second;tagBlockTestObj():first(0), second(0){}tagBlockTestObj( int i, int j ):first(i), second(j){}}BlockTestObj, *pBlockTestObj;// test object twotypedef 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
1 0
- 定长单元的批次内存缓存池的简洁实现
- 基于一个简单定长内存池的实现方法详解
- API实现批次序列号的销售出库
- API实现批次序列号的销售出库
- memcpy实现数组的定长复制
- 数据结构---串的定长顺序实现
- 数据结构——定长串的实现
- 简洁的单链表实现
- strcpy()的简洁实现
- 关于内存单元的想法
- 关于内存单元的一点点
- D3D 批次batch [Direct3D] 实现批次渲染、硬件 T&L 的渲染器和 D3DPipeline
- 关于批次的程序设计
- 批次管理的表
- JDBC的批次更新
- 一个简洁实用的PHP缓存类
- 串的定长存储
- 输出定长的string
- TiledMap 使用
- C/C++格式化字符串说明
- Android中关于Volley的使用(十)对Request和Reponse的认识
- 从计算的本质到编程语言
- 其他三次 只出现一次的数
- 定长单元的批次内存缓存池的简洁实现
- 再谈通过http访问SSAS
- LIB和DLL的区别与使用
- android触屏获取坐标
- Java测试用例
- Java的数据类型
- 【Linux 入门笔记】文本处理工具
- 方(芳)格(哥)取数
- 【学习笔记】android API 实用工具