zhuozhuo

 

一个内存池的实现

自定义内存池的思想通过这个"池"字表露无疑,应用程序可以通过系统的内存分配调用预先一次性申请适当大小的内存作为一个内存池,之后应用程序自己对内存 的分配和释放则可以通过这个内存池来完成。只有当内存池大小需要动态扩展时,才需要再调用系统的内存分配函数,其他时间对内存的一切操作都在应用程序的掌 控之中。[from IBM]

本人参考《C++应用程序性能优化》写出了完整的内存池实现代码,和大家交流。
如要了解内存池实现原理请打开网页:http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html

 1 #pragma once
 2 #define USHORT unsigned short
 3 #define ULONG unsigned long
 4 #include <iostream>
 5 using namespace std;
 6 //内存块声明和实现
 7 struct MemoryBlock
 8 {
 9     USHORT m_nSize;//可分配内存总大小
10     USHORT m_nFree;//可分配内存单元数目
11     USHORT m_nFirst;//第一个可用的内存单元位置
12     MemoryBlock* m_pNext;//指向下一个内存块
13     char m_data[1];
14     void* operator new(size_t,const USHORT& sum,const USHORT& unit_size)
15     {
16         return ::operator new(sizeof(MemoryBlock)+sum*unit_size);//申请一个内存块空间
17     }
18     void operator delete(void* del,size_t)
19     {
20         ::operator delete(del);//删除内存块空间
21     }
22     MemoryBlock(const USHORT& sum,const USHORT& unit_size)//sum为内存单元的个数,unit_size是每个单元的大小
23         :m_nSize(sum*unit_size),m_nFree(sum-1),m_nFirst(1),m_pNext(0)
24     {
25         char* pData=m_data;
26         for(int i=1;i<sum;i++)//初始化1到sum-1指向
27         {
28             *reinterpret_cast<USHORT*>(pData)=i;
29             pData+=unit_size;
30         }
31     }
32     ~MemoryBlock(){}
33 
34 };

 1 #pragma once
 2 #include "MemoryBlock.h"
 3 
 4 //内存池 a very good memory manager
 5 class MemoryPool
 6 {
 7 private:
 8     USHORT m_nUnitSize;//一个可分配单元的大小
 9     USHORT m_nInitSize;//第一个可分配空间数目
10     USHORT m_nGrowSize;//新增的可分配空间数目
11     MemoryBlock* m_pFirst;//指向第一个内存块
12 public:
13     //单元大小,第一个内存块的可分配空间数目,第二个内存块之后的可分配空间数目
14     MemoryPool(const USHORT& unit_size,const USHORT& init_size=2048,const USHORT& grow_size=1024);
15     ~MemoryPool(void);
16     void* Alloc();//分配内存
17     void Free(void* pfree);//回收内存
18     void FreeMemoryBlock(MemoryBlock *pblock);//销毁
19 };

 1 #include "MemoryPool.h"
 2 
 3 const USHORT MEMPOOL_ALIGNMENT=2;
 4 
 5 
 6 MemoryPool::MemoryPool(const USHORT &unit_size, const USHORT &init_size, const USHORT &grow_size)
 7     :m_pFirst(0),
 8      m_nInitSize(init_size),
 9      m_nGrowSize(grow_size)
10 {
11     if(unit_size>4)
12     {
13         m_nUnitSize = (unit_size + (MEMPOOL_ALIGNMENT-1)) & ~(MEMPOOL_ALIGNMENT-1);
14         //m_nUnitSize 取整到大于unit_size的最大的MEMPOOL_ALIGNMENT的倍数.
15         //令人纠结的注释
16     }
17     else if(unit_size>=2)
18         m_nUnitSize=4;
19     else
20         m_nUnitSize=2;
21 }
22 
23 void* MemoryPool::Alloc()//分配内存
24 {
25     if(!m_pFirst)//如果是第一次申请
26     {
27         MemoryBlock* pmb_first=new (m_nInitSize,m_nUnitSize)MemoryBlock(m_nInitSize,m_nUnitSize);//14日凌晨至此
28         m_pFirst=pmb_first;
29         return (void*)pmb_first->m_data;
30     }
31     MemoryBlock* pmb_block=m_pFirst;
32     while(pmb_block&&pmb_block->m_nFree==0)//pmb_block没走到最后并且当前block没有可分配结点
33     {
34         pmb_block=pmb_block->m_pNext;//往后走吧。
35     }
36     if(pmb_block)//如果找到可分配结点的block
37     {
38         char* pfree=pmb_block->m_data+(pmb_block->m_nFirst*m_nUnitSize);
39         pmb_block->m_nFirst=*((USHORT*)pfree);
40         pmb_block->m_nFree--;//可分配节点自减
41         return (void*)pfree;
42     }
43     else//如果找不到,此时pmb_block值为0
44     {
45         if(m_nGrowSize==NULL)
46             return NULL;
47         pmb_block=new (m_nGrowSize,m_nUnitSize)MemoryBlock(m_nGrowSize,m_nUnitSize);
48         if(!pmb_block)//new不成功
49             return NULL;
50         pmb_block->m_pNext=m_pFirst;//把新建的block放到最前吧
51         m_pFirst=pmb_block;
52         return (void*)pmb_block->m_data;
53     }
54 }
55 
56 void MemoryPool::Free(void* pfree)//回收内存
57 {
58     MemoryBlock* pmb_block=m_pFirst;
59     MemoryBlock* pmb_preblock=m_pFirst;
60     while((ULONG)pfree<(ULONG)pmb_block->m_data||
61         (ULONG)pfree>(ULONG)(pmb_block->m_data+pmb_block->m_nSize))//pfree不在当前block中
62     {
63         pmb_preblock=pmb_block;//前一个block块
64         pmb_block=pmb_block->m_pNext;
65         if(!pmb_block)//如果最后都没找到pfree的位置,则返回
66             return;
67     }
68     pmb_block->m_nFree++;//可分配数目+1
69     *((USHORT*)pfree)=pmb_block->m_nFirst;
70     pmb_block->m_nFirst=(USHORT)((ULONG)pfree-(ULONG)pmb_block->m_data)/m_nUnitSize;//m_nFirst指向新的可分配单元
71     if(pmb_block->m_nFree*m_nUnitSize==pmb_block->m_nSize)//如何该链块为空,则删除该块链
72     {
73         pmb_preblock->m_pNext=pmb_block->m_pNext;
74         if((ULONG)pmb_preblock==(ULONG)m_pFirst)
75             m_pFirst=NULL;
76         delete pmb_block;
77     }
78 }
79 
80 MemoryPool::~MemoryPool(void)
81 {
82     if(m_pFirst)
83         FreeMemoryBlock(m_pFirst);
84 }
85 
86 
87 void MemoryPool::FreeMemoryBlock(MemoryBlock *pblock)//销毁所有block。
88 {
89     if(pblock->m_pNext)
90         FreeMemoryBlock(pblock->m_pNext);
91     delete pblock;
92     pblock=NULL;
93 }
94

 1 #include "MemoryPool.h"
 2 #include "time.h"
 3 
 4 void performance_old()
 5 {
 6     clock_t start,stop;
 7     start = clock();//开始时间
 8     int i,b=0;
 9     for(i=0;i<=1000000;i++)
10     {
11       int* p=new int;
12     }
13 
14     cout<<"Without MemoryPool:"<<(double) (clock()-start)<<"ms"<<endl;//输出运行时间
15 }
16 
17 void memory()
18 {
19     clock_t start;
20     start = clock();//开始时间
21     MemoryPool mp(sizeof(int),1000,500);
22     int i=0;
23     for(i=0;i<=1000000;i++)
24     {
25       int* p=(int*)mp.Alloc();
26     }
27   
28     cout<<"Using MemoryPool:"<<(double)(clock()-start)<<"ms";//输出运行时间
29 }
30 int main()
31 {
32     performance_old();//传统的new操作
33     memory();//内存池
34     system("pause");
35     return 0;
36 }
本人新手,恳请众大鸟点评。

posted on 2009-04-15 20:46 卓卓 阅读(1762) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


导航

统计

公告

常用链接

留言簿(1)

随笔档案

文章档案

搜索

最新评论

阅读排行榜

评论排行榜