간단한 메모리풀 구현 (C++)

프로그래밍 일반에 관한 포럼입니다.

Moderator: 류광

Locked
Remisa
Posts: 290
Joined: 2006-07-10 02:25

간단한 메모리풀 구현 (C++)

Post by Remisa »

http://blog.naver.com/itioma/40032155038

C++ 로 구현할 수 있는 제일 덩치 작은 메모리 풀입니다.
헤더파일 하나, 소스파일 하나 받아가시면 되고요

(추가 - 현재 마지막 버전 : http://blog.naver.com/itioma/40040531964 )

사용법은

class A {...}; 이놈을

class A : public MemoryPooled {...}; 이렇게 바꾸기만 하면

new A 가 호출될 때마다 메모리 풀에서 적절한 메모리를 제공해줍니다.
delete A 가 호출되면 메모리를 회수해가고요.

풀 자체는 프로그램이 종료될 때 자동으로 사라집니다.
즉, 사용법이라곤 풀링을 원하는 클래스가 MemoryPooled 를 상속받도록 하는게 전부입니다.

주의점에 있듯이, new A[] 에 대해서는 관리해주지 않습니다.
왜냐면 제가 배열할당을 안쓰고 따로 만든 컨테이너를 쓰기 때문에... 그 기능은 안만들었죠 뭐. - _-

그리고 멀티쓰레드 지원 안합니다.
이것도 역시 제가 멀티쓰레드를 안쓰기 때문에... - _-

소스 길이를 보시면 알겠지만
그냥 '안쓰는 것보단 낫다' 정도만 만들어놨습니다.
(그래도 혼자 3시간이나 삽질하면서 만든거 ㅠ.ㅠ)
아 물론 메모리 단편화는 막아줍니다. 그것도 안된다면 메모리 풀이 아니죠.
한마디로 '메모리 풀 하나 쓰려고 다른 라이브러리를 통째로 끌어오긴 싫다'는 분들을 위한거.

메모리 체인은 EC++ Item 10 에 나와있는 방법을 사용했습니다.
EC++ 에 나온 방법은 클래스마다 풀을 달아줘야 한다는 단점이 있어서
너도나도 쓸 수 있는 공용 풀로 구현했습니다.

소스 공개되어있으니 분석해보시고
잘못된 부분 있으면 알려주시면 감사하겠습니다.
Last edited by Remisa on 2008-06-04 11:33, edited 2 times in total.
myevan
Posts: 1314
Joined: 2003-03-04 10:21
Contact:

Post by myevan »

공용으로 사용하는 풀이 있으면 편하기는 하지만
실제로는 클래스별로 풀이 있는 것이 지역성(한 시점에 사용하는 메모리는 근처인 경우가 많다.)면에서 더 좋습니다.

#1

Code: Select all

vector<Object*> objects;
for (int i = 0; i != OBJ_NUM; ++i)
    objects.push_back(new Object);

UseObjects(objects); 
#2

Code: Select all

Object objects[OBJ_NUM];
UseObjects(objects);
#1 과 #2 프로그램을 처음 실행할때는 성능은 거의 비슷합니다.

하지만 오래동안 실행되서 다른 코드에서 new, delete 가 많이 사용한 이후에
#2 의 objects[0] 과 objects[1] 거리는 언제나 sizeof(Object) 만큼이지만
#1 의 *objects[0] 과 *objects[1] 거리는 sizeof(Object) 보다 대개 늘어나게 됩니다.

이 거리가 운영체제가 관리하는 페이지 크기보다 커지면 실행 속도에 상당한 악영향을 미치게 됩니다.

----------------------------------
여기까지가 이론 설명이고...

코드 리뷰를 하면

Code: Select all

	int cellSize = ANC_SIZE+objSize;
	byte* newBlock = (byte*)malloc(MP_OBJ_PER_BLOCK * cellSize);
의도는 블럭 단위로 메모리를 할당하시려고 한 것 같은데
전혀 다르게 코딩 되신 것 같습니다.

구조체 512 정도를 할당하니 60000 이상이 할당되더라구요
메모리 관리 프로그램을 만들때는 최대 할당 크기를 별도로 계산해서 평가하는 테스트 루틴을
넣어두시는 것이 좋습니다.

Code: Select all

		for (int i=1; i<MP_OBJ_PER_BLOCK-1; ++i)
		{ // Form a linked list with memory cells
			nextAddress = newBlock + (i+1)*cellSize;
			memcpy(newBlock+i*cellSize, &nextAddress, ANC_SIZE);
		}
이 부분은 의도를 이해하기가 좀 힘듭니다.
메모리를 밀어주는 것 같은데, 방법을 다소 바꾸시면 불필요할듯해 보입니다.

memcpy(newBlock+i*cellSize, &nextAddress, ANC_SIZE); 에서 ANC_SIZE 의 경우 sizeof(void*) 인데,

Code: Select all

void* src = 뭔가 메모리 주소
void* dst = src; 
위처럼 하셔도 괜찮습니다.

newBlock + i*cell 보다는 블럭 구조체를 하나 만드셔서 포인터 연산하시는게 더 보기 좋습니다.

Code: Select all

byte*& nextFreeCell = nextFreeCellMap[size];

if (nextFreeCell == NOT_ASSIGNED ||
	size >= OBJ_SIZE_LIMIT)
{ // This memory does not belong to the memory pool! (user mistake?)
	::operator delete(pDeadObject); // Apply default delete operation.
	return;
}
이부분은 버그는 없지만 nextFreeCellMap[size] 에서 오버플로우가 한번 된다는 점이 좀 불안하죠 : )
빗자루네 http://www.myevan.net >_<b
비회원

Post by 비회원 »

C++에 대해선 무지해서 묻어가는 질문 하나 올립니다...;;
멀티 스레드의 경우 stl을 사용해서 메모리 풀을 적용할 수 있을까요?
(이펙티브 stl도 아직 못 본 지라... 그냥 쓰면 위험하다는 정도만 알고 있습니다..)
저같은 경우 고정 데이터 크기 셋을 처리하는 상황에서 정적배열을 쓰긴 했습니다만,
정렬이나 탐색 등의 면에서 좀 불편해서 바꿔볼까도 싶은데..
stl에 대해 잘 알지 못 하면서 쓰기는 좀 버겁네요..;;
Remisa
Posts: 290
Joined: 2006-07-10 02:25

Post by Remisa »

myevan//

공용 메모리 풀이라고 했지만
완전히 공용으로 사용하는 풀은 아니고
오브젝트 사이즈 (sizeof(object)) 별로 전용 메모리 블럭을 할당하는 풀입니다.
예를 들어 16byte 오브젝트용 메모리 블럭은
MP_OBJ_PER_BLOCK * (링크포인터 크기(4byte) + 16byte) 의 크기를 가지고,
MP_OBJ_PER_BLOCK 개의 16byte 오브젝트를 담을 수 있다는 식입니다.
다른 크기의 오브젝트를 위해서는 또다른 블럭이 생성됩니다.

따라서 정해진 사이즈의 블럭 구조체를 만들 수는 없었던 거죠.
항상 거기에 담을 객체의 사이즈에 비례하니까요.
(저도 + * 연산자로 포인터 연산하는거 굉장히 싫어합니다만 공교롭게도 이 경우에는 이게 제일 적합하더군요)

class A, B, C 등이 존재하고 각각의 사이즈가 서로 다를 때,
현재의 알고리즘에서는
갖가지 클래스들을 짬뽕으로 new/delete 하더라도
같은 클래스 사이에는 메모리 갭이 생기지 않습니다 블럭이 서로 다르니까요.

물론 사이즈가 서로 같은 클래스끼리는 같은 블럭을 공유하기 때문에
동일 클래스 기준으로 갭이 생길 수 있습니다.

기왕이면 사이즈 기준으로 하지 말고
말씀처럼 클래스마다 블럭을 분류해주면 더 좋은 성능이 나오겠지만

만약 사이즈가 작은 클래스끼리 블럭이 공유된다면 생각만큼 큰 갭이 생기지 않고
사이즈가 큰 클래스끼리는 둘의 사이즈가 동일할 확률이 떨어진다는 점,
(또한 사이즈가 큰 클래스를 여러번 new/delete하는 경우는 적다는 점)
그리고 클래스마다 분류하기 위해서는 현재의 단순한 인터페이스(MemoryPooled 상속으로 사용)를
포기해야 한다는 점에 착안해서 설계했습니다.

그리고 블럭 구조체가 없는 것과 같은 이유로 셀 구조체도 없기 때문에
링크포인터 영역을 따로 읽고 쓰기 위해서 memcpy 를 사용하게 되었습니다.
역시 공용으로 만들기 위해서는 참 많은 가독성을 희생하게 되더군요..
만들던 저도 헷갈릴 정도였는데 일단 쓰기 쉬운 풀을 만들겠다는 일념 하나로 버텼죠.

여기까지 이론 답변이었고 오버플로우 지적 감사합니다.
myevan
Posts: 1314
Joined: 2003-03-04 10:21
Contact:

Post by myevan »

공용을 위해 가독성을 포기하고 작성하셨다면
한번 특화된 형태로 가독성 높게 작성해보세요

그 다음에 다시 공용으로 만들어 보시면 좀 더 다른 코드 모양이 되어있을 것입니다 : )
빗자루네 http://www.myevan.net >_<b
Remisa
Posts: 290
Joined: 2006-07-10 02:25

Post by Remisa »

우움.. 사실 제가 제일 좋아하는 단어가 가독성인데
이렇게 완전 최말단 모듈인데다가 클래스는 커녕 자료형 개념조차 써먹을 수 없는 구석기시대같은 상황에서는
가독성을 유지할 방안이 안보이네요.
하필 속도가 생명인 부분이라 평소처럼 알기쉽게만 짜다보니 팍팍 느려지고..
확실히 루틴이 하위레벨로 들어갈수록 가독성 유지하기가 힘들다는 걸 느꼈습니다.
(단순히 변수이름 잘 정하는 정도의 의미는 아닙니다.)
괜히 서버 프로그래머는 C를 좋아하고 클라이언트 프로그래머는 C++를 좋아하는게 아닌 듯..

혹여나 제 것과 똑같은 일을 하면서 가독성도 훨씬 높은 코드를 짜는 사람을 본다면
사부로 모시던지 해야겠습니다.
myevan
Posts: 1314
Joined: 2003-03-04 10:21
Contact:

Post by myevan »

퇴근하고 여친 만나러 가는 길에 심심해서 한번 만들어 봤습니다 : )
조건이 "1024 크기 미만의 메모리만 풀링을 한다" 만 지키면 되는지요?
(코드내 vector 를 이미 쓰셨길래 똑같이 vector 를 썼습니다; )

급하게 짠거라 버그가 있을지 모르겠습니다만 : )

Code: Select all

#include <vector>
#include <algorithm>

class MemoryPool
{
public:
	enum
	{
		ALLOC_MAX_SIZE = 1024,
	};

public:
	~MemoryPool()
	{
		std::for_each(m_dataVector.begin(), m_dataVector.end(), free);
	}
	void* Alloc(int size)
	{
		if (size >= ALLOC_MAX_SIZE)
		{
			void* ret = malloc(size);;
			printf("::new\t%p:%d\n", ret, size);
			return ret;
		}

		std::vector<void*>& freeVector = m_freeVector[size];
		if (!freeVector.empty())
		{		
			void* ret = freeVector.back();
			freeVector.pop_back();
			printf("reuse\t%p:%d\n", ret, size);
			return ret;
		}

		void* ret = malloc(size);
		m_dataVector.push_back(ret);		
		printf("new\t%p:%d\n", ret, size);
		return ret;
	}
	void Free(void* ptr, int size)
	{
		if (size >= ALLOC_MAX_SIZE)
		{
			printf("::free\t%p:%d\n", ptr, size);
			free(ptr);
			return;
		}
		printf("free\t%p:%d\n", ptr, size);
		std::vector<void*>& freeVector = m_freeVector[size];
		freeVector.push_back(ptr);
	}

private:
	std::vector<void*> m_dataVector;
	std::vector<void*> m_freeVector[ALLOC_MAX_SIZE];
};

class MemoryPooled
{
public:
	virtual ~MemoryPooled() {}

	void* operator new(size_t size)
	{
		return s_pool.Alloc(size);
	}
	void operator delete(void* obj, size_t size)
	{
		s_pool.Free(obj, size);
	}

private:
	static MemoryPool s_pool;
};

MemoryPool MemoryPooled::s_pool;
아래는 테스트 프로그램입니다

Code: Select all

class A : public MemoryPooled {
};

struct B : MemoryPooled {
	char c;
};

struct C : MemoryPooled {
	short c;
};

class D : public MemoryPooled {
public:
	virtual ~D() {}
	char buf[100];
};


#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <assert.h>

#define New(T) test.push_back(new T);
#define Pop()  {delete test.back();test.pop_back();}
#define Del(i) {delete test[i];test.erase(test.begin()+i);}
#define NewChk(T, V) {T* o = new T; o->c = V;test.push_back(o);}
#define PopChk(T, V) {T* o = (T*)test.back();printf("%d\n", o->c);assert(o->c == V);delete test.back();test.pop_back();}

int main(int argc, char* argv[])
{
	{
		_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );	
		_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
		_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);	
	}

	std::vector<MemoryPooled*> test;
	New(A)
	Pop()
	NewChk(B, 1)
	NewChk(B, 2)
	New(C)
	New(D)
	Pop()
	Pop()
	PopChk(B, 2)
	PopChk(B, 1)
	return 0;
}
결과
new 00370FE0:4
free 00370FE0:4
new 003710C0:8
new 00371018:8
new 00371050:8
new 003711C0:104
free 003711C0:104
free 00371050:8
2
free 00371018:8
1
free 003710C0:8
ps.
MemoryPooled virtual 파괴자가 없어서 추가했더니 경고가 몇개 나는군요;
C:\libs\utils\mem_pool\mem_pool.cpp(124) : warning C4291: 'void *__cdecl MemoryPooled::operator new(unsigned int)' : no matching operator delete found; memory will not be freed if initialization throws an exception
C:\libs\utils\mem_pool\mem_pool.cpp(70) : see declaration of 'new'
delete(ptr, size); 형태는 첨이라;; 관련 내용은 밥먹고 심심해지면 추가하겠습니다.
빗자루네 http://www.myevan.net >_<b
Remisa
Posts: 290
Joined: 2006-07-10 02:25

Post by Remisa »

조건은
0. 제 풀의 소스보다 가독성이 뛰어나야 합니다.
1. size가 1024byte 미만인 클래스/구조체에 대한 메모리만 풀링을 합니다.
2. new [], delete [] 에 대해서는 풀링하지 않습니다.
3. MemoryPooled 를 상속하는 것만으로 사용할 수 있어야 합니다.
4. 여러 클래스에 대한 마구잡이 new/delete를 했을 때 소모시간이 제가 만든 풀보다 적거나 같아야 합니다.
5. C/C++ 표준에 있는 어느 문법이든 사용하실 수 있습니다. (STL 포함)

0번은 이 문제가 나온 목적이니 지켜져야 하는데, 여기서 걸릴 분은 없을듯 ^^;;
1번은 안 중요하고
2번은 별 상관 없고
3번이 중요하고
4번은 더 중요합니다.

메모리 풀을 쓰는 이유는 메모리 단편화를 막기 위해서고,
그걸 막으려는 가장 큰 이유가 바로 속도 때문이니까요(적어도 게임에서는요).
이 속도가 바로 가독성을 날려먹는 주범이기도 하죠.

5번은 제약조건이 아닙니다.
문법상의 제약이 없다는 뜻인데, STL이 결코 느린 구현물이 아니지만
지금 만드려는 것은 메모리에 직접 접근하는 메모리 풀이니까 나름 고민해가면서 써야겠죠.

다음은 테스트용 코드입니다.
테스트 사이즈 n을 주면
사이즈가 다른 3개의 클래스로 일부러 메모리 조각내기를 시도하면서
n제곱에 비례하는 new/delete를 먹인 후 총 경과시간을 체크해줍니다.
srand(0) 을 먹였으니까 항상 같은 패턴의 테스트를 보장해줍니다.
http://blogfile.paran.com/BLOG_335916/2 ... olTest.zip

테스트 결과는 이렇습니다.
경과시간:
Pool by Remisa < default new/delete < Pool by myevan
(물론 printf 는 지우고 테스트했습니다.)

즉 4번 조건을 충족시키지 못하셨습니다.
Last edited by Remisa on 2006-12-18 22:28, edited 4 times in total.
비회원

뭐하자는 건지..-_-

Post by 비회원 »

[인용]"즉 4번 조건을 충족시키지 못하셨습니다."

도데체 뭐하자는 건지요...
메모리풀 같은것들 인터넷 두둘기면 풀소스 통째로 있습니다.
요즘세상에 인터넷이 자료실인데 뭐가 없겠습니까..
메모리풀이던 뭐던 만들었으면 그냥 본인만 쓰세요..
만들고 나니 기쁘고 공개하고 싶은 마음은 이해하지만...
이건좀 아닌것 같네요..
Remisa
Posts: 290
Joined: 2006-07-10 02:25

Re: 뭐하자는 건지..-_-

Post by Remisa »

비회원 wrote:[인용]"즉 4번 조건을 충족시키지 못하셨습니다."

도데체 뭐하자는 건지요...
메모리풀 같은것들 인터넷 두둘기면 풀소스 통째로 있습니다.
요즘세상에 인터넷이 자료실인데 뭐가 없겠습니까..
메모리풀이던 뭐던 만들었으면 그냥 본인만 쓰세요..
만들고 나니 기쁘고 공개하고 싶은 마음은 이해하지만...
이건좀 아닌것 같네요..
어익후 이거 죄송해서 어쩌죠..
myevan
Posts: 1314
Joined: 2003-03-04 10:21
Contact:

Post by myevan »

흑 (-_-); 설마 결과가 왜 그렇게 나온건지 모르고 쓰신건 아니실테지만...
다소 흥분하신 상태에서 그런거라 생각하고...

Code: Select all

	MemoryPool2()
	{
		for (int i = 0; i != ALLOC_MAX_SIZE; ++i)
			m_freeVector[i].reserve(100*1024); // 사이즈는 적당히 잡아주세요

		m_dataVector.reserve(100*1024); // 사이즈는 적당히 잡아주세요
	}
vector 로 구현했으니; 적당한 크기로 reserve 해주면 속도가 빨라집니다.
이렇게 변경 하고 다시 테스트하면 거의 비슷한 속도가 납니다.

참고로 제가 좋아하는 풀은 아래와 같은 형태입니다.
http://www.myevan.net/phpBB/viewtopic.p ... MemoryPool
대부분 정적인 메모리를 사용해서 지역성을 높이고, 할당 한계를 넘어서면 자동으로 동적으로 메모리할당을 하게 합니다.
물론 공유 되지는 않습니다. 전 공유되는 메모리 풀은 별로 안 좋아하거든요 : )

개인적으로 자기가 작성한 코드를 공개하는 일은 좋다고 생각합니다.
평가 받는 다는건 쉬운 일이 아니거든요;; (= =)~

반가운 마음에 그냥 좀 더 개선할 수 있는 방향이 있다라는 점에서 이야기드린건데 기분이 상하셨던 것 같내요 : )
빗자루네 http://www.myevan.net >_<b
Remisa
Posts: 290
Joined: 2006-07-10 02:25

Post by Remisa »

myevan//

물론 reserve 해준 상태로 테스트했습니다.
그렇다면 제가 VC6.0 STL을 그대로 쓰다 보니 그 댓가를 치르는 듯..
(학교에 깔려있는게 그거라 따로 요즘버젼을 쓰기도 뭐하고)

흥분했다기보단 원래 제 말투가 쌀쌀맞습니다. 고쳐야 한다고는 생각하는데..
흥분했다면 지금 학교 과제가 밀려있어서 그런겁니다. ^^;

정적인 풀을 살펴보면 도움이 많이 될 것 같습니다. 자료 감사합니다.
류광
Posts: 3805
Joined: 2001-07-25 09:00
Location: GPGstudy
Contact:

Re: 뭐하자는 건지..-_-

Post by 류광 »

비회원 wrote:[인용]"즉 4번 조건을 충족시키지 못하셨습니다."

도데체 뭐하자는 건지요...
메모리풀 같은것들 인터넷 두둘기면 풀소스 통째로 있습니다.
요즘세상에 인터넷이 자료실인데 뭐가 없겠습니까..
메모리풀이던 뭐던 만들었으면 그냥 본인만 쓰세요..
만들고 나니 기쁘고 공개하고 싶은 마음은 이해하지만...
이건좀 아닌것 같네요..
만들었으면 공개, 공유하자는 게 GPG 시리즈의 취지이자 포럼의 취지이기도 합니다. Remisa님(및 회원분들), 이런 글은 대응하지 말고 무시하세요... 인용을 하면 지우기가 그렇거든요. (이 부분도 다시 생각 중입니다... 인용이 되었으므로 지워도 상관없지 않을까 하는...)
zupet
Posts: 2764
Joined: 2003-05-13 03:34
Location: NCSOFT LE팀

Post by zupet »

흥분하신 이유는 알 것 같습니다. 흐흐흐~
myevan wrote:퇴근하고 여친 만나러 가는 길에 심심해서 한번 만들어 봤습니다 : )
mesya
Posts: 268
Joined: 2005-02-28 20:08

Post by mesya »

의견을 주고받으며 더 좋은 방향으로 가기 위한 논쟁은 좋아 보입니다.
다만 감정싸움으로 물들지 않기를.......

...잘나오면 가져다가 잘 쓰겠습니다. 감사~ 히히~
이지노리, 김현중
비회원

Post by 비회원 »

저에게 더 좋은 생각이 있었다면 이 대회(?)에 참가를 했을터...ㅠ.ㅠ
Jacky
Posts: 59
Joined: 2004-06-01 09:36
Location: 게임공장

Post by Jacky »

저도 메모리 풀을 만들었었습니다.
저의 팀장님께서 지도해주셨었는데
operator new 에 대한 좋은 책은 more effective c++을 참고 했었고,
myevan님 소스도 참고해보고,
코드 프로젝트 등의 소스도 참고했지만 별로 안좋았던거 같았습니다.
제 것도 빗자루님거랑 구조가 거의 비슷해지더군요.

토의를 할때에는 신경이 날카로워 곤두서는 자세보다는
저사람의 의중과 의도를 파악해서 나에게 무엇을 가르치려하는가
부터 파악해서 받아들이고 잘못된점은 정중히 재질문식으로
집어주시는게 좋지 않을까 합니다..
myevan
Posts: 1314
Joined: 2003-03-04 10:21
Contact:

Post by myevan »

앗 -ㅅ-);; 어떤 분이 궁금증 올려서 답변을 만들었는데...

글이 사라졌군요;

Code: Select all

#include <stdio.h>

int main()
{
	char* p1 = new char[16];
	printf("p1 %p\n", p1);
	
	char* p2 = new char[16];
	printf("p2 %p\n", p2);

	char* p3 = new char[16];
	printf("p3 %p\n", p3);

	char* p4 = new char[16];
	printf("p4 %p\n", p4);

	char* p5 = new char[16];
	printf("p5 %p\n", p5);

	delete p2;
	delete p4;

	// 여기서 만약 메모리 풀 메모리를 할당한다고 생각하면...
	char* p6 = new char[16];
	printf("p6 %p\n", p6);


	delete p5;
	delete p3;
	delete p1;
	
	return 0;
}
vc6 컴파일 후 실행 결과는 이렇습니다.
p1 00370FE0
p2 00371028
p3 00371070
p4 003710B8
p5 00371100
p6 003710B8
p6 번은 p4 메모리가 재사용되고 있습니다.

만약 어떤 프로그램이 메모리 풀을 사용하지 않고
new/delete 를 반복한다면 드문드문 메모리가 할당되게 됩니다.

지역성 중요성에 대한 주요 사례는
1. 속도 최적화보다 크기 최적화가 요즘에는 더 빠르다.

2. 멤버들을 개별적으로 메모리 할당한 구조보다 한번에 할당한 구조가 더 빠르다.

Code: Select all

// #1
parent = new Parent;
parent->children = new Child[100];
// #2: 이쪽이 더 빠릅니다.
parent = malloc(sizeof(Parent) + sizeof(Child)*100)
3. 2와 비슷한 구조로 각 객체를 new 로 할당한 것보다 스택에 정적으로 선언한게 더 빠르다.

4. python 은 메모리 풀 도입으로 상당한 성능 향상을 보았다. (물론 alloc/free 코스트와 겹쳐지겠죠; )

5. mem[x][y][z] 보다 mem[z][y][x] 가 더 빠르다.
등등이 있습니다.

최적화에 너무 집중해서 가독성을 떨어뜨리는건 좋지 않지만
엇비슷한 가독성을 유지할 수 있다면 최적화 습관이나 이론적 지식은 가지고 있는 것이 좋습니다 : )
빗자루네 http://www.myevan.net >_<b
jinowin
Posts: 35
Joined: 2003-06-12 10:00
Contact:

new, delete 대상?

Post by jinowin »

myevan wrote:
#1

Code: Select all


vector <Object *> objects;
for (int i = 0; i != OBJ_NUM; ++i)
    objects.push_back(new Object);

UseObjects(objects); 
#2

Code: Select all

Object objects[OBJ_NUM];
UseObjects(objects);
#1 과 #2 프로그램을 처음 실행할때는 성능은 거의 비슷합니다.

하지만 오래동안 실행되서 다른 코드에서 new, delete 가 많이 사용한 이후에
#2 의 objects[0] 과 objects[1] 거리는 언제나 sizeof(Object) 만큼이지만
#1 의 *objects[0] 과 *objects[1] 거리는 sizeof(Object) 보다 대개 늘어나게 됩니다.

이 거리가 운영체제가 관리하는 페이지 크기보다 커지면 실행 속도에 상당한 악영향을 미치게 됩니다.
1번 코드의 의도가 vector< Object *> objects가 가르키는 Object *를 직접 new, delete 할 경우를 의미하나요?
myevan
Posts: 1314
Joined: 2003-03-04 10:21
Contact:

Post by myevan »

네 동적할당(#1) 이냐 정적할당(#2)이냐의 차이입니다.

요약하자면 정적할당과는 달리
동적할당은 프로그램 실행 시점에 따라 퍼포먼스의 변화가 생긴다라는 점을 이야기하고 싶었습니다.
빗자루네 http://www.myevan.net >_<b
Locked