CS

가비지 컬렉터

khkg12 2023. 12. 6. 23:29

C#은 C++과 달리 매니지드 힙이라는 개념이 도입, 즉 자동으로 힙영역의 메모리를 관리. 이를 가비지컬렉터가 관리해줌

 

매니지드 힙 : 메모리를 자동으로 관리해주는 힙

가비지컬렉터 (GC) 참조되지않는 메모리를 수집해서 해제해줌 

 

가비지컬렉터가 나온 배경 

1. 메모리누수 문제(Memory Leak)

2. 이중 해제 : 이미해제가 된 포인터(댕글링(Dangling Pointer) 포인터)를 해제하는 것

3. 이른 해제 : 사용이 끝나지 않았는데도(참조가 되는중) 해제하는 것

=> 스마트포인터도 이를 해결하기 위해 나온 것이지만 직접 사용해야함. 

 

매니지드힙은 순차적으로 메모리가 쌓이는 구조. 

 

특정조건에 루트를 돌면서 참조가 되고 있는지 확인 후 참조가 되고 있지 않는 놈들을 모아서 가비지컬렉터가 해제.

외부단편화가 일어났을 때 빈공간이 없도록 땡기는 것을 압축이라고함

 

압축에는 연산이 들어간다. 그래도 일반적으로 효율이 좋긴함. 하지만 유니티는 이과정이 없다. 즉 유니티의 Bohem GC는 비세대, 비압축이기에 오브젝트 풀링이 더 중요한것.

 

1세대 이후로도 새로운놈들이 생겼다고 쳤을 때 그놈들을 0세대로 친다. GC는 가장 낮은 세대인 0세대부터

탐색을 한다. 0세대를 탐색 후 지웠는데도 메모리가 부족하면 다음세대로 넘어간다. 그 숙청?과정이 끝난 후에도

살아남은 세대들은 한 세대씩 올려준다. 

0세대 부터 탐색하는 이유는 살아남은 애들은 자주 참조되는 가능성이 있기 때문이다. 

 

수집에서 살아남으면 다음세대로 승격. 통상 2세대까지. 수집은 낮은세대부터.

 

그런데 세대와 압축도 쓰는 방식이라면 큰 메모리가 처음 들어왔을 때 0세대가 아닌 2세대로 넘겨준다. (메모리가 크면 압축의 연산도 당연히 클테니까)  통상적으로 이러한 큰 메모리를 LOH라 부름. 바로 2세대에 때려넣어주면 압축의 연산이 들지않기 때문이다. 

즉 세대, 압축의 방식의 GC에서는 통상적으로 LOH (85kb보다 큰 개체)의 경우, 처음부터 끝세대에 할당해주는 것.