登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

秒大刀 博客

好好学习 天天向上

 
 
 

日志

 
 
 
 

MemoryPool  

2008-12-08 13:03:29|  分类: C/C++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

MemoryPool

        内存池这东西确实很有用。简单的说可以提高性能、减少碎片、帮助查错。MemoryPool的实现也有很多版本,SGI-STL里的实现就很不错。我自己也瞎折腾了一个Demo。

另外可以参考下相关的文章:

    C++ Memory Pool http://www.codeproject.com/KB/cpp/MemoryPool.aspx

    C++ Memory Pool 汉译版 http://blog.csdn.net/060/archive/2006/10/08/1326025.aspx

    Object Pooling for Generic C++ classes http://www.codeproject.com/KB/cpp/objpool.aspx

    Object Pooling using C# http://www.codeproject.com/KB/cs/ObjectPooling.aspx

    記憶體配置:Pooled Allocation技術評比與效能測試 http://blog.monkeypotion.net/gameprog/advanced/profiling-in-pooled-allocation-techniques#

#include <vector>

#include <map>

#include <set>

#include <cassert>

#include <algorithm>

 

/// @brief 禁用Win下的minmax宏。为啥要禁?请参阅《MACRO max & MACRO min》

#undef max

#undef min

 

class CMathUtility

{

public:

     /// @brief size向上取整到boundModule的倍数

     static size_t UpBoundTo(size_t size, size_t boundModule)

     {

         assert(boundModule > 0);

         if(size % boundModule != 0)

              size = (size / boundModule + 1) * boundModule;

         assert(size % boundModule == 0);

         return size;

     }

};

 

/// @brief 定长内存池实现

class CFixSizeMemoryPool

{

     typedef unsigned char byte_t;

public:

     CFixSizeMemoryPool(size_t nodeSize, size_t iniNodeCount, size_t nodeCountInBlock)

         : m_BlockCount(std::max(1U, nodeCountInBlock))

         , m_pFreeHead(NULL)

     {

         assert(nodeSize > 0);

         // 保证每个Block至少包含一个Node

         m_NodeSize = std::max(sizeof(byte_t*), nodeSize);

         // 分配初始内存

         if(iniNodeCount != 0)

         {

              const size_t c = iniNodeCount / m_BlockCount + (iniNodeCount % m_BlockCount != 0);

              for(size_t i = 0; i < c; i++)

                   AddNewBlock();

         }

     }

     ~CFixSizeMemoryPool()

     {

         for(std::vector<byte_t*>::const_iterator it = m_BlockAddr.begin(); it != m_BlockAddr.end(); ++it)

              delete[] (byte_t*)(*it);

         m_BlockAddr.clear();

     }

public:

     /// @brief 原生的内存分配。如果用于对象,请注意调用构造函数

     void* RawAlloc()

     {

         if(m_pFreeHead == NULL)

              AddNewBlock();

         byte_t* ret = m_pFreeHead;

         m_pFreeHead = *(byte_t**)m_pFreeHead;

         return ret;

     }

     template<typename T>

     T* Alloc()

     {

         assert(sizeof(T) <= m_NodeSize);

         return ::new(RawAlloc()) T();

     }

     template<typename T>

     void Free(T*& p)

     {

         byte_t* bp = (byte_t*)p;

#ifdef _DEBUG

         assert(p);

         bool checkflag = false;

         for(std::vector<byte_t*>::const_iterator it = m_BlockAddr.begin(); it != m_BlockAddr.end(); ++it)

         {

              if(bp >= *it && bp < *it + m_NodeSize * m_BlockCount)

              {

                   assert(((byte_t*)p - *it) % m_NodeSize == 0);

                   checkflag = true;

                   break;

              }

         }

         assert(checkflag);

#endif

         // 调用析构函数

         p->~T();

         // 将内存回收到内存池

         if(m_pFreeHead )

              *(byte_t**)m_pFreeHead = bp;

         m_pFreeHead = bp;

         p = NULL;

     }

public:

     /// @brief 该内存池可分配的每个节点的大小

     size_t NodeSize()const{return m_NodeSize;}

private:

     /// @brief 创建一个新的Block

     void AddNewBlock()

     {

         // 分配内存

         byte_t* pBuf = new byte_t[m_NodeSize * m_BlockCount];

         // 登记该次分配

         m_BlockAddr.push_back(pBuf);

         // 将新内存串成空闲链表

         byte_t* p = pBuf;

         for(size_t i = 0; i < m_BlockCount - 1; i++, p += m_NodeSize)

              *(byte_t**)p = (p + m_NodeSize);

         *(byte_t**)p = m_pFreeHead;

         // 更新空闲链头指针

         m_pFreeHead = pBuf;

     }

private:

     size_t m_NodeSize;                   ///< 每个内存Node的大小(字节)

     size_t m_BlockCount;                 ///< 每个Block中包含的Node的个数

 

     byte_t* m_pFreeHead;                 ///< 未使用内存的头指针

     std::vector<byte_t*> m_BlockAddr;    ///< 该池占用的所有Block的头指针

};

 

/// @brief 自适应内存池实现

class CMemoryPool

{

     typedef unsigned char byte_t;

public:

     CMemoryPool()

     {

     }

     ~CMemoryPool()

     {

         for(std::map<size_t, CFixSizeMemoryPool*>::const_iterator it = m_poolList.begin(); it != m_poolList.end(); ++it)

         {

              delete it->second;

         }

         m_poolList.clear();

     }

public:

     bool AddSubPool(size_t size, size_t nodeCountInBlock)

     {

         if(ExistSubPool(size))

              return false;

         m_poolList[size] = new CFixSizeMemoryPool(size, 0, nodeCountInBlock);

         return true;

     }

     bool ExistSubPool(size_t size)const

     {

         return m_poolList.find(size) != m_poolList.end();

     }

public:

     /// @brief 原生的内存分配。如果用于对象,请注意调用构造函数

     void* RawAlloc(size_t size)

     {

         CFixSizeMemoryPool* pool = FindSubPool(size);

         if(pool)

              return pool->RawAlloc();

         else

         {

              byte_t* p = new byte_t[size];

#ifdef _DEBUG

              std::pair<std::set<void*>::iterator, bool> iret = m_notPoolList.insert(p);

              assert(iret.second);

#endif

              return p;

         }

     }

     template<typename T>

     T* Alloc()

     {

         return ::new(Alloc(sizeof(T))) T();

     }

     template<typename T>

     void Free(T* p)

     {

         CFixSizeMemoryPool* pool = FindSubPool(sizeof(T));

         if(pool)

              pool->Free(p);

         else

         {

#ifdef _DEBUG

              size_t eret = m_notPoolList.erase(p);

              assert(eret == 1);

#endif

              p->~T();

              delete[] (byte_t*)p;

         }

     }

private:

     CFixSizeMemoryPool* FindSubPool(size_t size)

     {

         std::map<size_t, CFixSizeMemoryPool*>::iterator it = std::lower_bound(m_poolList.begin(), m_poolList.end(), std::map<size_t, CFixSizeMemoryPool*>::value_type(size, NULL));

         if(it != m_poolList.end())

         {

              assert(it->first >= size);

              return it->second;

         }

         return NULL;

     }

private:

     std::map<size_t, CFixSizeMemoryPool*> m_poolList;

#ifdef _DEBUG

     std::set<void*>    m_notPoolList;

#endif

};

 

 

#include <iostream>

using namespace std;

void main()

{

     CFixSizeMemoryPool pool(sizeof(int), CMathUtility::UpBoundTo(7, 8), 1);

     int* p = pool.Alloc<int>();

     *p = 9;

     cout << *p << endl;

     pool.Free(p);

     cout << p << endl;

}

 

  评论这张
 
阅读(2529)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018