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

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

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

內(nèi)存池是自己向OS請(qǐng)求的一大塊內(nèi)存,自己進(jìn)行管理。

##系統(tǒng)調(diào)用## 我們先測(cè)試系統(tǒng)調(diào)用new/delete的用時(shí)。

#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;
}

用時(shí)為604124400ns。系統(tǒng)的new是在堆上分配資源,每次執(zhí)行都會(huì)分配然后銷毀。

##簡(jiǎn)單的內(nèi)存池##

#include <iostream>
#include <time.h> 
using namespace std;
char buf[4100]; //已分配內(nèi)存
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;
}

用時(shí)為39420791ns,后者比前者快20倍。

簡(jiǎn)單內(nèi)存池在開始在全局/靜態(tài)存儲(chǔ)區(qū)分配資源,一直存在。每次重載的new調(diào)用只是返回了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; //一個(gè)單元的內(nèi)存大小
	unsigned long m_ulBlockSize; //整個(gè)內(nèi)存池的內(nèi)存大小
public:
	CMemPool(unsigned long lUnitNum = 50, unsigned long lUnitSize = 1024);
	~CMemPool();
	void* Alloc(unsigned long ulSize, bool bUseMemPool = true);
	void Free(void* p);
};

CMemPool定義了一個(gè)_Unit來管理鏈表,指針被包含在整個(gè)結(jié)構(gòu)中,這種方式和內(nèi)核中的鏈表寫法很像。

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

C++內(nèi)存池實(shí)現(xiàn)

 

它被均分為lUnitNum個(gè)大小為m_ulUnitSize Byte的小內(nèi)存塊。每個(gè)塊分為2部分:Unit鏈表管理頭真正進(jìn)行存儲(chǔ)的內(nèi)存單元

從圖中可以看出m_ulBlockSize的計(jì)算方式為:

UnitNum * ( UnitSize + sizeof(Struct _Unit))

然后用雙向鏈表連接所有的小塊。m_pFreeMemBlock指向空閑的內(nèi)存的起始位置,m_pAllocatedMemBlock指向已分配出去的內(nèi)存的起始位置。

##MemPool實(shí)現(xiàn)##

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;
		}
	}
}

構(gòu)造函數(shù)設(shè)置默認(rèn)的小塊數(shù)為50,每個(gè)小快大小為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的作用是分配內(nèi)存,返回分配的內(nèi)存地址,注意加上Unit的大小是為了略過Unit管理頭。實(shí)質(zhì)是把m_pFreeMemBlock指向的free內(nèi)存移動(dòng)到m_pAllocatedMemBlock指向的已分配內(nèi)存里。

每次分配時(shí),m_pFreeMemBlock指針后移。pCurUnit從前面插入到m_pAllocatedMemBlock里。

void CMemPool::Free(void* p)
{
	if(m_pMemBlock<p && p<(void*)((char*)m_pMemBlock + m_ulBlockSize))
	{
		//判斷釋放的內(nèi)存是不是處于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的作用是釋放內(nèi)存,實(shí)質(zhì)是把m_pAllocatedMemBlock指向的已分配內(nèi)存移動(dòng)到m_pFreeMemBlock指向的free內(nèi)存里。和Alloc的作用相反。

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

##測(cè)試##

#include "mempool.h"
#include <time.h> 
CMemPool g_MemPool;
class CTestClass
{
public:
	void *operator new(size_t);	 //重載運(yùn)算符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的內(nèi)存給它
}
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;
		//使用內(nèi)存池測(cè)試
		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;
		
		//使用系統(tǒng)調(diào)用測(cè)試
		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;
}

##結(jié)果##

從下圖可以看出,只有當(dāng)程序頻繁地用系統(tǒng)調(diào)用malloc/free或者new/delete分配內(nèi)存時(shí),內(nèi)存池有價(jià)值。

C++內(nèi)存池實(shí)現(xiàn)

 

分享到:
標(biāo)簽:內(nèi)存
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定