日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

內存池是自己向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來管理鏈表,指針被包含在整個結構中,這種方式和內核中的鏈表寫法很像。

m_pMemBlock指向分配的那塊大小為m_ulBlockSize的大內存的地址。m_pMemBlock是線性的內存,我們把它用下列這種方式管理。

C++內存池實現

 

它被均分為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))
	{
		//判斷釋放的內存是不是處于CMemPool
		cout << "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);
	}
}

Free的作用是釋放內存,實質是把m_pAllocatedMemBlock指向的已分配內存移動到m_pFreeMemBlock指向的free內存里。和Alloc的作用相反。

pCurUnit要減去struct _Unit是為了從存儲單元得到管理頭的位置,堆是向上生長的。

##測試##

#include "mempool.h"
#include <time.h> 
CMemPool g_MemPool;
class CTestClass
{
public:
	void *operator new(size_t);	 //重載運算符new
	void operator delete(void *p);
	
private:
	char m_chBuf[1000];
};
void *CTestClass::operator new(size_t uiSize)
{
	return g_MemPool.Alloc(uiSize); //分配g_MemPool的內存給它
}
void CTestClass::operator delete(void *p)
{
	g_MemPool.Free(p);
}
class CTestClass2
{
private:
	char m_chBuf[1000];
};
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;
	for(int iTestCnt=1; iTestCnt<=10; iTestCnt++)
	{
		unsigned int i;
		//使用內存池測試
		clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
		for(i=0; i<100000*iTestCnt; i++)
		{
			CTestClass *p = new CTestClass;	
			delete p;
		}
		clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
		
		cout << "[ Repeat " << 100000*iTestCnt << " Times ]" 
		<< "Memory Pool Interval = " << diff(time1,time2).tv_nsec 
		<< "ns" << endl;
		
		//使用系統調用測試
		clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
		for(i=0; i<LOOP_TIMES; i++)
		{
			CTestClass2 *p = new CTestClass2;	
			delete p;
		}
		clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
		cout << "[ Repeat " << LOOP_TIMES << " Times ]" 
		<< "System Call Interval = " << diff(time1,time2).tv_nsec 
		<< "ns" << endl;
	}
	return 0;
}

##結果##

從下圖可以看出,只有當程序頻繁地用系統調用malloc/free或者new/delete分配內存時,內存池有價值。

C++內存池實現

 

分享到:
標簽:內存
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定