加载中…
正文 字体大小:

内存池

(2012-12-09 10:56:05)
标签:

杂谈

内存池
    Created by pritry
    有人怀疑过内存池的能力,理由是malloc在操作系统层面到应用层之间这个层面上也有对内存碎片的自动整理,就像glibc中的malloc也是通过链表标记录内存块的的使用状况标记的,具有自动整理未使用碎片的功能,在 malloc之上再建立内层池,增大了软件层次上的复杂性。这怀疑得有道理,不过并不完全正确了,malloc下的等大小的内存块不可能适应所有系统架构,频繁的整理并不没有考虑整个系统的性能,在mallocn层次下一次申请大块内存,等价于跳过该层次直接从操作系统层面上建立新的层面。
    STL的内存管理机制应该耳熟能详了,把内存分为小块和大块,小块以8的倍数递增,共16个小块,大块用作大内存申请需求,当内存管理本质以链表形式,以union作为共用体节省指针的开销。申请与释放内存块就是在链表中进行标记,对剩余块进行合并等,可以看看侯捷的STL源码剖析。Java虚拟机和Python虚拟机中的内存管理主要以引用方式记录内存使用状况,由于它们的用途主要是构建各种解释器语言的type和variant的使用状况,模拟CPU的寄存器和堆栈执行流程,需要对这些引用状况频繁地进行更新操作,因此就有了垃圾回收的树型结构的说法,在引入树型式的管理时,就需要借助如三色颜色标记状态,根据最近使用时间序列,计数器标记等方法进行剪枝和更新,在被引用的内存块中可以进行一些交换车箱式的火车算法管理改理将相互引用的对象放在同上车厢,或者进行堆合并。回收更新利用多线程定时器可以完成。nginx服务器的管理方式也是大同小异了,不过内存池更有针对性了,具体是对网络work工作者线程,网络request和connection级的线程,整个进程级别的各种优先级内存池进行hash链表式管理。将小块内存的申请聚集到一起申请,然后一起释放。避免了频繁申请小内存,降低内存碎片的产生,其次引内存日志和对齐原则等。
下面举几个内存池的例子:
①Ring buffer

//Created by pritry

CRingBuffer::CRingBuffer(int  nSize)  

{  

   assert(nSize >= 0);  

   m_pBuffer = NULL;  

   Reset(nSize);  

}  

CRingBuffer::~CRingBuffer(void)  

{  

   if (m_pBuffer)  

   {  

      delete[] m_pBuffer;  

      m_pBuffer = NULL;  

   }  

}  

void CRingBuffer::Reset(int nSize)  

{  

   if(m_pBuffer != NULL)  

   {  

      delete[] m_pBuffer;  

      m_pBuffer = NULL;  

   }  

 

   m_nBufferSize = nSize;  

 

   if(m_nBufferSize > 0)  

   {  

      m_pBuffer = new char[m_nBufferSize];  

      m_pDataEnd = m_pDataStart = m_pBuffer;  

   }  

}  


void CRingBuffer::ReSize(int nSize)  

{  

   assert(nSize > 0);  

 

   if(m_pBuffer != NULL)  

   {  

      char* p = new char[nSize];  

      int n = nSize > FillSize() ? FillSize():nSize;  

 

      memcpy(p, m_pDataStart, n);  

 

      delete[] m_pBuffer;  

 

      m_pBuffer = p;  

      m_nBufferSize = nSize;  

      m_pDataStart = p;  

      m_pDataEnd = p + n;  

   }  

   else  

   {  

   Reset(nSize);  

   }  

}  

bool CRingBuffer::Read(char* &pData, int nSize, bool nMove)  

{  

   Data = NULL;  

 

   if(FillSize() < nSize)  

      return false;  

 

   pData = m_pDataStart;  

 

   if(nMove)  

   {  

      m_pDataStart = m_pDataStart + nSize;  

   }  

 

   return true;  

}  


bool CRingBuffer::Write(char* pData, int nSize)  

{  

   if(m_nBufferSize - FillSize() < nSize)  

   {  

      return false;  

   }  

 

   memcpy(m_pDataEnd, pData, nSize);  

   m_pDataEnd = m_pDataEnd + nSize;  

 

   return true;  

}  

int CRingBuffer::FillSize()  

{  

   assert(m_pDataEnd - m_pDataStart >= 0);  

   return m_pDataEnd - m_pDataStart;  

}  

int CRingBuffer::GetBufferSize() const  

{  

   return m_nBufferSize;  

}  

①Pool buffer

//Created by pritry

union List 

 char szData; 
 union List* pNext; 
}; 

class CMemoryPool 

public: 
 CMemoryPool  (); 
 virtual ~CMemoryPool  (); 
 
 static bool CreatePool(int nSize); 
 static void DestroyPool(); 
 
 static void* AllocateMemory(int nSize); 
 static void DeallocateMemory(void* p, int nSize); 
 
private: 
 static void* AllocateSystemMemory(int nSize); 
 static void DeallocateSystemMemory(void* p, int nSize); 
 static char* AllocatePoolMemory(int nSize, int nCount); 
 
public: 
 static char* pHashFirst; 
 static char* pHashLast; 
 
private: 
 static List* volatile m_pMemoryList[LIST_NUM]; 
}; 
void* CMemoryPool::AllocateSystemMemory(int nSize) 

 void* result = NULL; 
 
 if(nSize > 0) 
 
  try 
  
   result = new char[nSize]; 
  
  catch (std::bad_alloc e) 
  
   return NULL; 
  
  return result; 
 
 
 return result; 

char* CMemoryPool::AllocatePoolMemory(int nSize, int nCount) 

 nSize = (nSize + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1)); 
 int n = nSize*nCount; 
 char* result; 
 int nBytesFree = (int)(pHashLast - pHashFirst); 
 
 if(nBytesFree >= n) 
 
  result = pHashFirst; 
  pHashFirst += n; 
  
  return result; 
 
 else if(nBytesFree >= nSize) 
 
  nCount = nBytesFree / nSize; 
  n = nSize * nCount; 
  
  result = pHashFirst; 
  pHashFirst += n; 
  
  return result; 
 
 else 
 
  int nNewSize = 2*n; 
  
  if(nBytesFree > 0) 
  
   List* volatile * pCurrentList = m_pMemoryList + (nBytesFree + ALIGN_SIZE - 1) / (ALN_SIZE - 1); 
   ((List*)pHashFirst)->pNext = *pCurrentList; 
   *pCurrentList = (List*)pHashFirst; 
  
  
  pHashFirst = (char*)AllocateSystemMemory(nNewSize); 
  
  if(pHashFirst == NULL) 
  
   return NULL; 
  
  
  pHashLast = pHashFirst + nNewSize; 
  
  return AllocatePoolMemory(nSize, nCount); 
 

0

阅读 评论 收藏 转载 喜欢 打印举报
已投稿到:
  • 评论加载中,请稍候...
发评论

       

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 不良信息反馈 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有