-
Notifications
You must be signed in to change notification settings - Fork 0
메모리 관리
mooneegee edited this page Feb 18, 2014
·
1 revision
소프트웨어의 성능은 알고리듬과 메모리 활용에 의해 결정된다. 메모리가 성능에 영향을 끼치는 형태는 다음과 같다.
- 동적 메모리 할당, malloc이나 C++의 전역 new 연산자는 매우 느리다. 동적 메모리 할당을 피하거나 할당하는 비용을 줄일 수 있는 allocator(동적 할당자)를 직접 만들어야 한다.
- memory access pattern(메모리 접근 패턴)에 좌우되는 경우도 많다. 시스템 아키텍쳐 시간에 배운 memory locality를 생각하면 쉽게 이해할 수 있다.
heap allocation(malloc(), free(), C++의 전역 new 연산자 및 delete 연산자 등)은 매무 느리다. 느린 원인은 두 가지이다.
- 힙 할당자는 범용 목적이기 때문에 1바이트에서 수 기가까지 어떤 크기의 할당이라도 처리할 수 있어야 하는데 이렇게 하면 관리하는 부가적인 비용이 든다.
- malloc()과 free()를 호출할 때 대부분 운영체제에서는 먼저 유저 모드에서 커널 모드로 context-switch를 하고, 필요한 동작을 수행한 후 다시 프로그램으로 context-switch을 해야 한다. windows 실습 시간에 context-switch를 수행할 때 발생하는 비용에 대해서 배웠으니 교재를 참고하길 바란다.
그래서 다음을 반드시 지키기위해서 노력해야 한다. 게임 개발에 있어서 Golden Rule이라고 한다.
힙 할당은 최소화하고 tight loop 안에서는 절대 힙 할당을 하지 말 것!
그런데 현실적으로 동적 메모리 할당을 전혀 하지 않기란 불가능하다. 해결책은 allocator를 제작해서 쓰는 것이다. allocator의 장점은 다음과 같다.
- 미리 할당된 메모리 블록을 이용할 수 있다. 이 경우 운영체제의 커널 모드로 context-switch가 필요없이 유저 모드에서만 동작하는 이점이 있다.
- 사용 패턴을 예측할 수 있기 때문에 범용 힙 할당자에 비해 훨씬 효율적으로 동작할 수 있다.
stack에 관한 설명은 생략하겠다. marker는 top-pointer를 roll-back할 때 필요하다. 할당된 두 블록의 정확한 경계 지점이 있어야 해제할 때 top-pointer를 어디로 내릴지 알 수 있기 때문이다. 그래서 스택 할당자는 보통 현재 스택 꼭대기를 나타내는 marker를 리턴하는 함수를 제공한다. top-pointer를 내리는 roll-back함수는 marker를 함수의 인자로 받는다.
class StackAllocator
{
public :
// 스택 마커 : 현 시점의 스택 꼭대기를 나타낸다.
// 롤백할 때는 임의의 주소로 할 수 없고 반드시 marker의 위치로만 할 수 있다.
typedef U32 Marker;
// 전체 크기를 인자로 받아 스택 할당자를 생성한다.
explicit StackAllocator(U32 stackSize_bytes);
// 스택의 꼭대기에 주어진 위치만큼 할당한다.
void * alloc(U32 size_bytes);
// 현재 스택의 꼭대기를 표시하는 마커를 리턴한다.
Marker getMarker();
// 이전의 마커 위치로 롤백한다.
void freeToMarker(Marker marker);
// 스택 전체를 비운다.(스택을 0의 위치로 롤백한다.)
void clear();
private :
// ...
};
-
Memory leak
할당된 메모리가 제때 해제되지 않는 것으로 out of memory를 초래할 수 있다. -
Memory corruption
엉뚱한 메모리 주소를 변경해 원래 있던 정보를 날려 버리고 정작 변경됐어야 할 메모리 위치의 값은 고쳐지지 않는 것을 말한다.