项目名称:内存池
环境:VS2010
内容:利用链表存数组的形式
实现目的:系统中的new和delete调用比较消耗资源,设计一个相对消耗较小的对象池
大致思想:一个链表指向空闲内存,分配就是取出一块来,改写链表,返回,释放就是放回到链表里面,并做好归并。注意做好标记和保护,避免二次释放,还可以花点力气在如何查找最适合大小的内存快的搜索上,减少内存碎片
这里假设申请了12个字节大小的空间释放了三个字节
最后一个释放的空间存空,倒数第二个存倒数第一个释放的地址,以此类推,直至没有释放的空间,这样做是为了方便再次分配
实现一个 BlockNode,每个 BlockNode用于分配固定大小的内存块,比如用于分配 32字节对象的固定内存分配器,之类的。这个固定内存分配器回收的时候,统一把先前向系统申请的内存块全部还给系统。
按照不同对象大小(8字节,16字节,32,64,128,256,512,1K。。。64K),构造十多个固定内存分配器,分配内存时根据内存大小查表,决定到底由哪个分配器负责
代码
#include <iostream>
using namespace std;
#include <vector>
#include <string>
template<class T>
class ObjectPool
{
struct BlockNode
{
void* _memory;
BlockNode* _next;
size_t _objNum;
BlockNode(size_t objNum)
:_objNum(objNum)
,_next(NULL)
{
_memory=malloc(_itemSize*_objNum);
}
};
protected:
size_t _countIn;//当前节点用的计数
BlockNode* _first;
BlockNode* _last;
size_t _maxNum;//节点申请内存块对象大小
static size_t _itemSize;//单个对象大小
T* _lastDelete;
public:
ObjectPool(size_t initNum=32,size_t maxNum=10000)
:_countIn(0)
,_maxNum(maxNum)
,_lastDelete(NULL)
{
_first=_last=new BlockNode(initNum);
}
~ObjectPool()
{
_Destory();
_countIn=0;
_maxNum=0;
_first=NULL;
_last= NULL;
_lastDelete=NULL;
}
T* New()
{
//1.优先申请以前释放过的空间
//2.内存块里面申请
//3.申请新的节点对象
if(_lastDelete)
{
T* obj=_lastDelete;
_lastDelete=*((T**)_lastDelete);
return new(obj)T;
}
if (_countIn>=_last->_objNum)
{
size_t objNum=GetObjNum(_last->_objNum);
_last->_next=new BlockNode(objNum);
_last=_last->_next;
_countIn=0;
}
T* obj1=new((T*)((char*)_last->_memory+_itemSize*_countIn))T();
_countIn++;
return obj1;
}
void Delete(T* ptr)
{
if(ptr)
{
*(T**)ptr=_lastDelete;
_lastDelete=ptr;
}
}
static size_t InitItemSize()//初始化单个对象
{
if(sizeof(T)<sizeof(void*))
{
return sizeof(void*);
}
else
{
return sizeof(T);
}
}
size_t GetObjNum(size_t Oldsize)//下一个对象空间大小
{
size_t objsize=2*Oldsize;
if(objsize>_maxNum)
{
return _maxNum;
}
else
{
return objsize;
}
}
void _Destory()//销毁函数
{
BlockNode* cur=_first;
while (cur)
{
BlockNode* del=cur;
cur=cur->_next;
free(del->_memory);
del->_objNum=0;
delete del;
}
}
};
template<class T>
size_t ObjectPool<T>::_itemSize=ObjectPool<T>::InitItemSize();//静态对象类外进行赋值
///
// 测试内存对象池的常规使用和内存对象的重复使用
void TestObjectPool()
{
vector<string*> v;
ObjectPool<string> pool;
for (size_t i = 0; i < 32; ++i)
{
v.push_back(pool.New());
printf("Pool New [%d]: %p\n", i, v.back());
}
while (!v.empty())
{
pool.Delete(v.back());
v.pop_back();
}
for (size_t i = 0; i < 32; ++i)
{
v.push_back(pool.New());
printf("Pool New [%d]: %p\n", i, v.back());
}
v.push_back(pool.New());
}
#include <Windows.h>
// 针对当前的内存对象池进行简单的性能测试
void TestObjectPoolOP()
{
size_t begin , end;
vector<string*> v;
const size_t N = 10000;
v.reserve(N);
cout<<"pool new/delete==============================="<<endl;
// 反复申请释放5次
begin = GetTickCount();
ObjectPool<string> pool;
for (size_t i = 0; i < N; ++i)
{
v.push_back(pool.New());
}
while (!v.empty())
{
pool.Delete(v.back());
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(pool.New());
}
while (!v.empty())
{
pool.Delete(v.back());
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(pool.New());
}
while (!v.empty())
{
pool.Delete(v.back());
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(pool.New());
}
while (!v.empty())
{
pool.Delete(v.back());
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(pool.New());
}
while (!v.empty())
{
pool.Delete(v.back());
v.pop_back();
}
end = GetTickCount();
cout<<"Pool:"<<end - begin<<endl;
cout<<"new/delete==============================="<<endl;
begin = GetTickCount();
for (size_t i = 0; i < N; ++i)
{
v.push_back(new string);
}
while (!v.empty())
{
delete v.back();
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(new string);
}
while (!v.empty())
{
delete v.back();
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(new string);
}
while (!v.empty())
{
delete v.back();
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(new string);
}
while (!v.empty())
{
delete v.back();
v.pop_back();
}
for (size_t i = 0; i < N; ++i)
{
v.push_back(new string);
}
while (!v.empty())
{
delete v.back();
v.pop_back();
}
end = GetTickCount();
cout<<"new/delete:"<<end - begin<<endl;
}
与new、delete比较
未完,持续更新