内存池是自己向OS请求的一大块内存,自己进行管理 。
##系统调用## 我们先测试系统调用new/delete的用时 。
#include <IOStream>
#include <time.h> using namespace std;class TestClass{private: char m_chBuf[4096];};timespec diff(timespec start, timespec end){ timespec temp; temp.tv_sec = end.tv_sec-start.tv_sec; temp.tv_nsec = end.tv_nsec-start.tv_nsec; return temp;}int main(){ timespec time1, time2; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); for(unsigned int i=0; i< 0x5fffff; i++) { TestClass *p = new TestClass; delete p; } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); cout<<diff(time1,time2).tv_sec<<":"<<diff(time1,time2).tv_nsec<<endl;}用时为604124400ns 。系统的new是在堆上分配资源,每次执行都会分配然后销毁 。
##简单的内存池##
#include <iostream>#include <time.h> using namespace std;char buf[4100]; //已分配内存class TestClass{public: void* operator new(size_t) {return (void*)buf;} void operator delete(void* p){}private: char m_chBuf[4096];};int main(){ timespec time1, time2; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1); for(unsigned int i=0; i< 0x5fffff; i++) { TestClass *p = new TestClass; delete p; } clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2); cout<< diff(time1,time2).tv_sec<<":"<<diff(time1,time2).tv_nsec<< endl;}用时为39420791ns,后者比前者快20倍 。
简单内存池在开始在全局/静态存储区分配资源,一直存在 。每次重载的new调用只是返回了buf的地址,所以快 。
##MemPool定义##
class CMemPool{private: struct _Unit {struct _Unit *pPrev, *pNext; }; void* m_pMemBlock; struct _Unit* m_pFreeMemBlock; struct _Unit* m_pAllocatedMemBlock;unsigned long m_ulUnitSize; //一个单元的内存大小 unsigned long m_ulBlockSize; //整个内存池的内存大小public: CMemPool(unsigned long lUnitNum = 50, unsigned long lUnitSize = 1024); ~CMemPool(); void* Alloc(unsigned long ulSize, bool bUseMemPool = true); void Free(void* p);};CMemPool定义了一个_Unit来管理链表,指针被包含在整个结构中,这种方式和内核中的链表写法很像 。
【C++内存池实现】m_pMemBlock指向分配的那块大小为m_ulBlockSize的大内存的地址 。m_pMemBlock是线性的内存,我们把它用下列这种方式管理 。
文章插图
它被均分为lUnitNum个大小为m_ulUnitSize Byte的小内存块 。每个块分为2部分:Unit链表管理头,真正进行存储的内存单元 。
从图中可以看出m_ulBlockSize的计算方式为:
UnitNum * ( UnitSize + sizeof(Struct _Unit))然后用双向链表连接所有的小块 。m_pFreeMemBlock指向空闲的内存的起始位置,m_pAllocatedMemBlock指向已分配出去的内存的起始位置 。
##MemPool实现##
CMemPool::CMemPool(unsigned long ulUnitNum, unsigned long ulUnitSize):m_pMemBlock(NULL), m_pAllocatedMemBlock(NULL), m_pFreeMemBlock(NULL),m_ulBlockSize(ulUnitNum * (ulUnitSize+sizeof(struct _Unit))),m_ulUnitSize(ulUnitSize){ m_pMemBlock = malloc(m_ulBlockSize); if(NULL != m_pMemBlock) {for(unsigned long i = 0; i<ulUnitNum; i++){struct _Unit* pCurUnit=(struct _Unit*)((char*)m_pMemBlock+ i*(ulUnitSize+sizeof(struct _Unit)) );pCurUnit->pPrev = NULL;pCurUnit->pNext = m_pFreeMemBlock;if(NULL != m_pFreeMemBlock){m_pFreeMemBlock->pPrev = pCurUnit;}m_pFreeMemBlock = pCurUnit;} }}构造函数设置默认的小块数为50,每个小快大小为1024,最后用双向链表管理它们,m_pFreeMemBlock指向开始 。
void* CMemPool::Alloc(unsigned long ulSize, bool bUseMemPool){ if(ulSize > m_ulUnitSize || false == bUseMemPool || NULL == m_pMemBlock || NULL == m_pFreeMemBlock) {cout << "System Call" << endl;return malloc(ulSize);} struct _Unit *pCurUnit = m_pFreeMemBlock; m_pFreeMemBlock = pCurUnit->pNext; if(NULL != m_pFreeMemBlock) {m_pFreeMemBlock->pPrev = NULL; } pCurUnit->pNext = m_pAllocatedMemBlock; if(NULL != m_pAllocatedMemBlock) {m_pAllocatedMemBlock->pPrev = pCurUnit; } m_pAllocatedMemBlock = pCurUnit; cout << "Memory Pool" << endl; return (void*)((char*)pCurUnit + sizeof(struct _Unit));}Alloc的作用是分配内存,返回分配的内存地址,注意加上Unit的大小是为了略过Unit管理头 。实质是把m_pFreeMemBlock指向的free内存移动到m_pAllocatedMemBlock指向的已分配内存里 。
每次分配时,m_pFreeMemBlock指针后移 。pCurUnit从前面插入到m_pAllocatedMemBlock里 。
void CMemPool::Free(void* p){ if(m_pMemBlock<p && p<(void*)((char*)m_pMemBlock + m_ulBlockSize)) {//判断释放的内存是不是处于CMemPoolcout << "Memory Pool Free" << endl;struct _Unit* pCurUnit = (struct _Unit*)((char*)p -sizeof(struct _Unit));m_pAllocatedMemBlock = pCurUnit->pNext;if(NULL != m_pAllocatedMemBlock){m_pAllocatedMemBlock->pPrev == NULL;}pCurUnit->pNext = m_pFreeMemBlock;if(NULL != m_pFreeMemBlock){m_pFreeMemBlock->pPrev = pCurUnit;}m_pFreeMemBlock = pCurUnit; } else {free(p); }}
推荐阅读
- 手机电池裸露的电极有什么用?智能机电池为什么不可拆解?
- 微信朋友圈图片及聊天内容占用内存,应该怎么删除?
- 为什么会产生内存碎片?
- 世界上最危险的泳池 世界上最神奇的游泳池
- CPU处理器|DDR5内存五大升级都有啥?最后一个你绝对想不到
- 含模型 动力电池成本结构拆分
- iPhone换电池,是原装电池好还是换第三方大容量电池好?
- 为什么智能手机都取消了手机内存卡槽?看完算搞懂了
- 把微信这2个功能关掉,手机释放大量内存,涨知识了
- 电脑内存怎么清理