메모리 구조와 GC
Intro
개발을 할 때 메모리를 효율적으로 사용해야한다는 말을 들어본적이 있을것이다. 우리가 게임을 만들 때 메모리가 언제 어떻게 사용되는지 알고있다면 보다 더 효율적인 개발을 할 수 있을 것이다.
메모리 구조
- 위는 일반적으로 표현하는 컴퓨터 메모리 구조이다.
- 메모리는 크게 코드영역, 데이터영역, 힙영역, 스택영역으로 나뉜다.
코드영역
- 코드영역은 내가 작성한 Script 들이 저장되는 곳이다. 컴퓨터가 코드영역에 저장된 명령(스크립트의 명령들)을 하나씩 가져와 처리한다.
데이터영역
- 데이터영역은 전역변수와 정적변수가 저장되는 곳이다.
- 여기에 저장된 메모리는 프로그램이 끝날 때 까지 없어지지 않고 남아있게된다.
- 따라서 너무많은 전역/정적 변수를 사용하게 되면 메모리를 많이 차지하게된다.
public float speed;
public Transform myPos;
public static bool isWalk;
...
스택영역
- 스택영역에는 지역변수 또는 매개변수를 저장한다. 이때 저장된 데이터들은 코드블럭이 끝나면 소멸한다.
void Update()
{
Enemy enemy = new Enemy();
Vector3 nextDir = transform.position - enemy.transform.position;
...
}
- 위와 같은 코드에서, 지역변수는 enemy와 nextDir가 있다.
- 지역변수 nextDir의 Vector3값은 스택에 저장되지만, enemy에는 new 키워드로 새로운 객체를 생성하여 지역변수 enemy에 저장했기 때문에 이 값은 힙 영역에 저장된다.
- C#에서 new로 생성되는 모든 참조형 객체는 힙 영역에 저장되기 때문이다.
- 여기서 new Enemy()로 만든 객체가 있는 “주소값”이 스택영역에 저장된다.
- 따라서 Vector3 값과 enemy의 주소값은 매 프레임마다 생성되고 소멸되기를 반복하게 ㅗ딘다.
힙영역
- 힙영역은 프로그래머가 직접 메모리에 할당해주는 영역이다.
- 프로그래머가 new로 생성하는 모든 참조형 객체는 이 힙영역에 저장된다.
- 하지만 힙영역에 저장된 값들은 코드블럭이 끝나도 사라지지 않는다. 따라서 위의 예시에서 매 프레임마다 생성된 enemy 객체들은 계속해서 쌓이게 된다.
Garbage Collection(GC)
- 이렇게 계속해서 힙영역에 사용되지 않는 데이터들이 쌓이게 되면 사용가능한 메모리가 없어져 더이상 새로운 값을 할당할 수 없고, 결국엔 프로그램이 멈춰버리게 된다.
- 이를 해결하기 위하여 C#에는 GC라는것이 존재하여 이것이 힙에서 쓰이지않는 데이터들을 자동으로 제거해준다.
- 그렇다면 프로그래머는 GC를 믿고 메모리 관리를 하지않아도 될까?
- 아쉽지만 GC가 힙에 있는 데이터를 정리할 때 매우 많은 성능을 잡아먹게된다.
- 따라서 무자비하게 객체를 생성하는 행위는 좋지않다.
- 마찬가지로 GC가 많이 호출되지 않도록 하는것이 좋다.
댓글남기기