책보다가 클래스 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 |