Memory Pool (메모리 풀)

C++ 2010. 11. 13. 01:12

책보다가 클래스 operator new, delete 를 재정의하여 메모리를 미리 잡아놓고 분양해서 쓰는 소스를 봤는데..

개념은 간단한데 문법이 이해가 안간다. 인터넷에서도 설명해주신 분들이 계신데 봐도 이해가 안간다.
(메모리 풀 사용시 기본 new, delete 에서의 시스템 콜이 없어지고 클래스에서 사용할 메모리 캐싱으로 인한 속도 향상이 기본 개념)
일단 소스는..
 
MemoryPool.h :  메모리 풀
#pragma once

#include <windows.h>
#include <assert.h>

template <class T, int ALLOC_BLOCK_SIZE = 50>
class CMemoryPool
{
public:
	static VOID* operator new(std::size_t allocLength)
	{
		assert(sizeof(T) == allocLength);
		assert(sizeof(T) >= sizeof(UCHAR*));

		if (!mFreePointer)
			allocBlock();

		UCHAR* ReturnPointer = mFreePointer;
		mFreePointer = *reinterpret_cast<UCHAR**>(ReturnPointer);

		return ReturnPointer;
	}

	static VOID operator delete(VOID* deletePointer)
	{
		*reinterpret_cast<UCHAR**>(deletePointer) = mFreePointer;
		mFreePointer = static_cast<UCHAR*>(deletePointer);
	}

private:
	static VOID allocBlock(void)
	{
		mFreePointer = new UCHAR[sizeof(T) * ALLOC_BLOCK_SIZE];

		UCHAR** Current = reinterpret_cast<UCHAR**>(mFreePointer);
		UCHAR *Next = mFreePointer;

		for (INT i = 0; i < ALLOC_BLOCK_SIZE - 1; ++i)
		{
			Next += sizeof(T);
			*Current = Next;
			Current = reinterpret_cast<UCHAR**>(Next);
		}
		*Current = 0;
	}
private:
	static UCHAR *mFreePointer;
protected:
	virtual ~CMemoryPool()
	{
	}
};

template <class T, int ALLOC_BLOCK_SIZE>
UCHAR* CMemoryPool<T, ALLOC_BLOCK_SIZE>::mFreePointer;

​

이해 안되는 부분은 
UCHAR* ReturnPointer = mFreePointer;
mFreePointer = *reinterpret_cast<UCHAR**>(ReturnPointer);
allocBlock()에서 다음 블락의 주소를 넣어준건 이해하겠는데
*reinterpret_cast<UCHAR**>(ReturnPointer); 이게 어떻게 다음 블락을 가리키게 되는지 이해가 안간다.
내눈엔 *(UCHAR**)ReturnPointer 로만 보이는데... 물어볼 사람도 없고 외롭네..
 
어쨌든 CMemoryPool를 상속한 클래스와 일반 클래스의 new/delete 의 속도 성능은 5배 정도 향상된다.
(책에선 10배. 메모리만 터지지 않으면 캐싱은 위대하다.)
 
main.cpp : 테스트
#include <iostream>
using namespace std;

#include "CheckTime.h"
#include "MemoryPool.h"
class CDataMP : public CMemoryPool<CDataMP>
{
public:
	CDataMP() {}
private:
	BYTE a[1024];
	BYTE b[1024];
};

class CData
{
public:
	CData() {}
private:
	BYTE a[1024];
	BYTE b[1024];
};
void main(void)
{

	CCheckTime CheckTime;
	CheckTime.start();

	for (INT i = 0; i < 1000000; i++) // 수행 결과 : 약 1395 ms
	{
		CData *pData = new CData();
		delete pData;
	}

	cout << CheckTime.end() << endl;
	CheckTime.start();


	for (INT i = 0; i < 1000000; i++) // 수행결과 약 : 240 ms
	{
		CDataMP *pData = new CDataMP;
		delete pData;
	}

	cout << CheckTime.end() << endl;
}


 
CheckTime.h : 수행시간 체크하기 위해 만든 클래스
#pragma once
#include <windows.h>

class CCheckTime
{
public:
	CCheckTime() {}
	~CCheckTime() {}
	void start(void)
	{
		if (QueryPerformanceFrequency(&freq) != 0)
		{
			isStart = TRUE;
			QueryPerformanceCounter(&startTime);
		}
	}

	double end(void)
	{
		if (isStart == FALSE) return -1;

		QueryPerformanceCounter(&endTime);
		double elapsedTime = ((double)(endTime.QuadPart - startTime.QuadPart) / freq.QuadPart);
		elapsedTime *= 1000; //msec

		isStart = FALSE;

		return elapsedTime;
	}
private:
	BOOL isStart;

	LARGE_INTEGER freq;
	LARGE_INTEGER startTime;
	LARGE_INTEGER endTime;

};​



 
 
참고 자료

'C++' 카테고리의 다른 글

[MFC] 인터넷 HTML 소스 다운로드  (1) 2010.12.01
윈도우 서비스 (service)  (0) 2010.11.25
performance counter (성능 모니터링)  (0) 2010.11.25
MiniDump (미니 덤프 생성하기)  (0) 2010.11.13
virtual 와 상속 속성  (0) 2010.11.10
stable priority queue  (0) 2010.11.08
log4cxx  (0) 2010.11.06
Singleton (싱글톤)  (0) 2010.11.05