一个依靠STL vector的接口进行申请和回收管理的内存池类( c++ 封装)

C++ 实现高性能内存池 一、概述 在 C/C++ 中,内存管理一个非常棘手的问题,我们在编写一个程序的时候几乎不可避免的要遇到内存的分配逻辑,这时候随之而来的有这样一些问题:是否有足够的内存可供分配? 分配失败了怎么办? 如何管理自身的内存使用情况? 等等一系列问题。在一个高可用的软件中,如果我们仅仅单纯的向操作系统去申请内存,当出现内存不足时就退出软件,是明显不合理的。正确的思路应该是在内存不足的时,考虑如何管理并优 阅读详情

问题描述:

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
c++实现内存池并应用到STL容器 内存池: 为了节省申请小块内存与释放小块内存时的开销,可以使用内存池,开始时根据需要申请一片较大的内存,在申请小块内存的时候从内存池中获取,在释放小块内存时,将内存放回内存池 内存池中的内存块: 块的大小可以由内存池的编写者确定,一般为8的倍数:8,16,24,32,.....,128;单位为字节,相同大小的块通过指针串成一串(单链表一样) 内存池的两个部分: ... 阅读详情

相关推荐

STLvector():常见接口、短字符串优化SSO、vector的模拟实现(重要)

STL 的string怎么啦?C++面试中string的一种正确写法C++ STL string的Copy-On-Write技术C++std::string的“读时也拷贝”技术!

m0_73975164的博客 1291

基于STL内存池

基于STL封装内存池,已经在linux下做过稳定性测试。

Mtour's blog 632

C++ vector 内存释放

C++ STL容器 vector 的工作原理 vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储,似数组的内存结构。 系统预先给vector容器分配一块 capactity 大小的内存空间,当插入的数据超过这个空间的时候,这块空间会让某种方式扩展,即通过一定倍数大小重新分配空间、拷贝元素、撤销旧空间,在vs下为1.5倍扩容,在linux下为2倍扩容。但是为了防止大量分配连续内存的开销,在使用clearerase删除数据的时候,它只做了数据清除工作,没有释放内存,所以vector

hallyz的博客 3244

内存池介绍

文章目录1.什么是内存池1.1池化技术1.2内存池2.为什么需要内存池3.内存池的发展3.1早期内存池3.2定长内存池分配器3.3哈希映射的FreeList内存池4.实现一个定长内存池 1.什么是内存池 1.1池化技术 池是计算机中常用的一种设计模式,其特点是将资源提前申请好,放在’‘资源池’'之中由程序自己控制资源的使用,这样减少了与内核的交互 因为资源的申请是需要通过内核来完成的,与内核交互的频率越高, 程序的效率就越低,提前将资源申请出来,使用资源的时候不需要再向内核申请,直接就可以使用,在一定程度上

ych9527的博客 1122

C++ 设计内存池的一些记录

内存池是池化技术中的一种形式。通常我们在编写程序的时候回使用newdelete这些关键字来向操作系统申请内存,而这样造成的后果就是每次申请内存释放内存的时候,都需要操作系统的系统调用打交道,从堆中分配所需的内存。如果这样的操作太过频繁,就会找成大量的内存碎片进而降低内存的分配性能,甚至出现内存分配失败的情况。而内存池就是为了解决这个问题而产生的一种技术。

m0_73915763的博客 177

一个简单内存池的实现

栈(放指针)+对象池重载了具体对象的operator new缺点:没有用数组,还是存在malloc的空隙.  在一个长时间运行的系统中(一个httpserver),内存的分配释放操作很频繁. 如果只是按照平常的编程模式, 在需要内存时在堆中分配,在使用完后立即释放, 效率会很低. 因为在c++中,系统默认的newdelete操作为了兼顾所有的情况,效率很低,同时,反复的内存分

gaoteng1984的专栏 1593

c++ vector 自定义内存分配器到栈内存

C++ vector

hackin 2130

STLvector!!!

本文讨论了有关STL库中vector的相关知识,欢迎大家我一起交流、学习、进步!

2501_90507065的博客 1581

C++进阶()STL大法--vector的深度剖析以及模拟实现

C++的顺序表vector深度剖析,本篇文章将带你熟悉vector的各个接口函数的使用,并且介绍算法库的算法:find,swapsort的用法,最后介绍vector模拟实现中与容量相关的函数实现以及构造函数,析构函数拷贝构造函数的具体实现,内附代码图文讲解,看完真能学会!

杭电码农-NEO的博客 1822

STL-内存池

qq_55439426的博客 1748

C++学习10-STL内存池

内存池STL介绍内存分配内存池的思路内存池特点为什么要有空间配置器一些知识点开辟内存为什么要考虑内存对齐nginx内存池的大块内存小块内存的界小块内存为什么不提供释放函数重置函数ngx_reset_pool什么时候调用惊群现象nginx适合短链接 参考博文链接在这里 STL介绍 STLC++ 标准程序库的核心。STL 内的所有组件都由模板构成,其元素可以是任意型别。程序员通过选用恰当的群集...

sunshine612的博客 1057

STL库——vector函数学习)

本文介绍了C++标准库中vector容器的基本使用方法常见成员函数。主要内容包括:vector的四种构造函数(默认构造、n个value构造、迭代器区间构造拷贝构造);运算符重载([]访问比较运算符);插入删除函数(push_back、pop_back、insert、erase);容量管理函数(reserve、resize、size、capacity等);以及三种遍历方式(下标、迭代器范围for)。文章还比较了vector与string的异同,并指出vector没有重载流操作符的原因。

2302_80177460的博客 1076

C++vector的使用及模拟实现

C++vector的使用及模拟实现部分函数讲解

渣檬Charman的博客 1162

C++】透过STL源码深度剖析及模拟实现vector

STLvector的深度剖析及模拟实现

做技术人 · 产优质博客 · 找好工作 1670

C++STLvector的使用及其模拟实现

本文详细介绍了STLvector的使用及其模拟实现,希望对您有所帮助,感谢您的支持

qq_67582098的博客 912

C++STLvector(超详解)

vector就是数组,动态增长的顺序表。它string的区别是什么呢?一个管理任意型的数组,一个管理管理字符数组。为了提高内存申请释放的效率,它的内存都不是直接从计算机来的,它是从内存池来的。学习vector的成本其实非常低,因为我们之前学习过string,并且vector其实就是一个顺序表。

庖丁解牛,恢恢乎游刃有余 837

C++】一文带你走入vector

vector的使用,vector iterator的使用,vector空间增长问题,vector增删查改

m0_57388581的博客 6205
上一篇: c++封装的用来存储key value pair的内存池类
manthink2005
博客等级 码龄18年 3粉丝 30原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值