CS, 기술면접

가비지 컬렉터 (Garbage Collector)

동윤큐 2023. 10. 13. 15:54
가비지 컬렉터 (GC) 

 

자동 메모리 관리 기능, 미사용 메모리를 파악하고 해제하는 프로세스 (.Net CLR 위에서 기능 제공)
Heap 영역에서 동적으로 할당했던 메모리  필요 없게 된 메모리 객체(garbage)를 모아 주기적으로 제거하는 프로세스

 

Unity에서는 가비지 컬렉터를 사용하여 애플리케이션과 Unity에서 더 이상 사용하지 않는 오브젝트로부터 메모리를 회수합니다.

 

GC는 내부적으로 상당한 CPU 사용량을 요구한다. 불필요하게 GC가 자주 실행되면 프로그램 실행을 멈추는 현상을 유발한다. 따라서 GC가 필요 이상으로 실행되지 않도록 하는 것이 중요하다.

 

GC 발동 조건

 

1. 시스템 메모리가 실제로 부족할 경우

2. 관리되는 힙의 할당된 객체에 사용되는 메모리가 허용되는 임계값을 초과한 경우

3. 수동으로 GC.Collect 메서드를 호출한 경우

 

GC 작동 원리

 

■ 메모리 할당

1. C#은 선형적인 힙(관리되는 힙) 메모리를 가지며, 메모리 할당을 위한 포인터를 가짐

2. 메모리 할당이 필요한 경우 객체에 필요한 메모리 크기 만큼 증가시키고, 포인터도 증가한 크기만큼 증가

3. 메모리 할당을 위한 충분한 메모리 공간이 없을 경우 GC가 호출되고, 그럼에도 충분한 공간이 없을 경우 힙 메모리가 확장 

 

힙 메모리 할당

 

 

■ 메모리 해제

1. CLR에서 GC Root 래퍼런스 집합을 살펴본다.

2. GC Root가 래퍼런싱 하는 객체들을 타고 들어가, 경로에 있는 객체들을 모두 alive로 마킹함

3. 마킹되지 않은 메모리를 해제하며 사용중인 메모리는 당겨주는 재배치 과정을 함(Compact) 

 

힙 메모리 해제

 

 

세대별 GC

 

CLR은 메모리를 효율적으로 관리하기 위해 세대를 나눈다. 0, 1, 2세대로 나누며

최근 할당된 메모리부터 GC가 한번 불릴 때마다 살아남은 메모리까지 0-2세대로 나눈다.

최근 생성된 객체일수록 메모리 해제가 발생할 가능성이 높기 때문에 0세대의 메모리부터 관리하고 0에서 살아남은 메모리는 1세대가 되며, 1세대 GC가 일어나고 살아남은 메모리가 2세대가 된다.

 

GC의 세대별 관리

 

2세대 힙이 오브젝트로 가득차게 되면 Full GC가 된다. 일반적으로 CLR이 애플리케이션을 일시 정지하고 모든 세대에 다시 GC를 실행한다. (멀티스레드를 사용하여 처리도 가능함)

 

■ SOH, LOH

C#은 객체의 크기에 따라 메모리를 크게 두가지로 나눠 관리함

SOH (Small Object Heap) - 85KB 미만 용량이 작은 객체(오브젝트)

LOH (Large Object Heap) - 85KB 이상 용량이 큰 객체(오브젝트)

 

SOH는 0,1,2로 세가지 세대로 나누어 메모리를 관리, SOH는 GC가 발생하면 해제된 메모리 공간들에 사용중인 메모리들로 재배치

LOH는 2세대만 관리, LOH는 메모리를 해제하면 메모리가 큰 오브젝트 재배치 하는 것은 오버헤드가 크기 때문에 재배치 하는 작업을 하지 않는다.

 

Unity vs .Net GC 차이점

 

# Unity는 재배치(Compact) 과정을 안한다 .Net은 재배치를 하여 자유 메모리 공간을 확보해줌. 여기서 자유 메모리는 해제되고 비어있는 메모리 공간을 말하며 .Net은 사용 중인 메모리를 당겨주는 작업을 하고 Unity는 오버헤드로 인해 공간을 놔두어 이를 메모리 단편화라고 부르며 힙에 메모리가 충분히 남더라도 단편화된 메모리에 연속적인 공간이 충분히 없으면 힙을 늘려주는 작업을 한다. (현재 더 공부중이며 여기까지가 현재 알고있는 지식)

유니티는 Boehm–Demers–Weiser 가비지 컬렉터 를 사용한다. 점진적 GC를 사용