티스토리 뷰

C & C++

[C++] 메모리풀(MemoryPool) 만들기

강씨아저씨 2016. 2. 1. 21:30

게임 서버 프로그래밍 책을보다가 기초라이브러리 제작목록에 유용한 코드들이 있어서


따라해봤다. 앞으로 책을읽다 흥미가 가는 코드들은 따라해본다음 포스팅할 예정이다...

오늘은 메모리풀(MemoryPool)이다. 


메모리풀은 같은객체의 new / delete가 반복적으로 일어나면 프로그램 속도에 영향을 주기때문에

미리 특정공간만큼을 확보해둔후 new / delete 호출시에 미리 확보된 공간을 제공, 회수함으로써

프로그램의 속도를 높이는 방법이다. 

설명은 이쯤에서 그만하고 소스코드를 보겠다. 

준비물은 <iostream>과 <windows.h>이다.

CMemoryPool.h
 

#include <windows.h>

#include <iostream>

 

template <class T, int ALLOC_BLOCK_SIZE = 50 >

class CMemeoryPool

{

public:

static VOID* operator new(std::size_t allocLength)

{

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()

{

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:

~CMemeoryPool()

{

}

};

 

 

template <class T, int ALLOC_BLOCK_SIZE>

UCHAR* CMemeoryPool<T,ALLOC_BLOCK_SIZE>::mFreePointer;


이 코드의 특징은 메모리영역 확보후 객체(T) 사이즈 만큼의 메모리를 건너뛰면서 

메모리의 앞 4바이트에 다음객체(T)의 주소를 넣는것이다. 

만약 어떤클래스의 크기가 8바이트고 메모리풀 사이즈가 4라면 다음과 같을것이다.



 

프로그래머가 new 시에 앞에 4바이트를 읽어서 mFreePoint를 이동시킨후 해당 메모리 공간을 건내주게된다.

delete시에는 삭제를 원하는 메모리의 앞에 4바이트에 mFreePoint를 저장한후 mFreePoint를 삭제를 원하는 메모리의 시작주소로 옮긴다.


속도차이를 확인하기 위한 코드는 다음과 같다. 

main.cpp

#include "CMemoryPool.h"

 

 

class CDataMP : public CMemeoryPool<CDataMP>

{

public:

BYTE a[1024];

BYTE b[1024];

};

 

class CDataMP2

{

public:

BYTE a[1024];

BYTE b[1024];

};

 

int main()

{

 

int FOR_COUNT = 1000000;

clock_t start_time, end_time; 

 

start_time = clock();                  // Start_Time

 

   

for(int i=0; i<FOR_COUNT; i++)

{

CDataMP* pData = new CDataMP();

delete pData;

}

end_time = clock();                   // End_Time

printf("[메모리풀 사용] Time : %f\n", ((double)(end_time-start_time)) / CLOCKS_PER_SEC); 

 

start_time = clock();                  // Start_Time

 

   

for(int i=0; i<FOR_COUNT; i++)

{

CDataMP2* pData = new CDataMP2();

delete pData;

}

end_time = clock();                   // End_Time

    printf("[메모리풀 사용하지 않음] Time : %f\n", ((double)(end_time-start_time)) / CLOCKS_PER_SEC); 

 

 

return 0;

}

결과 화면이다.  약 4.5배의 차이가 났다.



누군가에게는 작은도움이 되었기를 바라면서 오늘의 포스팅 끝~

댓글