본문 바로가기

Language/C#

GC / SGen

-Garbage Collector 


Garbage Collection을 수행하는것



-Garbage Collection 


메모리 기법중의 하나로 프로그램이 동적으로 할당했던 메모리 영역중에서 필요없게 된 영역을 해제하는 기능

존 매카시가 개발했다.

('Mark&Compact Algorithm'을 사용하여 더이상 참조하지 않는 객체를 분별한다.)


GC 수집조건은 system의 실제 memory가 부족하거나, Managed heap의 할당된 object에 사용되는 memory가 

허용되는 임계값을 초과할때, GC.Collect method를 호출할 떄 작동한다.




-장점


유효하지 않은 포인터 접근을 방지해준다.

이중해제를 방지해준다.

메모리누수를 바지해준다.



-단점


어떤 메모리를 해제할지 결정하는데 비용이 많이든다.

쓰레기 수집이 일어나는 타이밍이나 점유시간을 예측하기 힘들다.

할당된 메모리가 해제되는 시점을 알수없다.



-Stop-the-world  


GC를 실행하기 위해 Application 실행을 멈추는것, Stop the world가 발생하면

GC를 실행하는 thread를 제외한 나머지 thread들은 모두 작업을 멈추고 GC작업이 완료되어야 다시 작업을 시작한다.





가비지컬렉터가 가비지컬렉션을 수행함으로서 메모리를 관리하는것이다.




GGC 방식(Generational GC)


GC는 Generation별로 나누어 Memory를 관리한다.

(Memory를 관리하는 공간이 3개이며 0, 1, 2 Generation별로 나누어 관리)

최초에 할당된 Memory는 무조건 0이라는 공간에서 관리하고 GC가 한번 실행된 이후에도 살아있는 0 Generation 메모리들은 1 Generation로 이동하고 1 Generation에서 GC가 일어나서 살아남은 메모리들은 2 Generation로 이동한다.


낮은 Generation일수록 GC작업이 더 자주 발생한다.


장점


memory 파편화가 없다.


단점


여러개로 나누어져 관리하는 메모리 영역이라 하더라도 메모리 크기가 크고 많은 memory가 있다면 순회, 해제하는데 오래걸린다.

memory를 여러개로 나누어 관리하기떄문에 memory 공간이 많이 부족해진다.






-GC 관리법


1.코드에서 System.GC.Collect()를 이용해서 직접 GC를 수행하는것은 가급적 피한다.

객체가 사용중인지 확인하는 작업과 객체들의 빈자리를 매꾸기 위해 재배치작업(Compaction작업)을 수행하기 때문이며

객체가 다음Generation으로 승격되기때문에 더 이상 사용하지 않는다 하더라도 GC작업으로 해당 객체가 정리될 확률이 줄어들기 떄문이다.


2.사용하지 않는 객체는 GC가 수집할 수 있는 대상으로 설정한다.

null값을 대입해주거나 using을 이용해서 객체의 사용하는 범위를 지정해준 다음 Dispose()를 구현하여

해당객체에서 사용했던 객체들을 해지시켜주는 방법


3.자주사용하는 객체는 전역변수로 잡아서 garbage를 최소화 할것







Mono 2.8 부터 GC알고리즘은 SGen으로 변경되었다.

Mono 2.8 이전에는 GC알고리즘은 Boehm 기반으로 작동하였다.(해당 알고리즘은 Mark And Sweep을 기반으로 개발됨)

Unity의 경우 Boehm기반 GC를 사용한다.



SGen(Simple Genrational GC / Xamarin에서 사용)


SGen의 경우 Nursery, Major Heap 단 2개의 세대만 존재한다.

객체 할당은 Nursey에서만 일어나며 일정횟수의 GC에서 살아남은 메모리들을 Major Heap으로 승진시킨다.

2개의 세대 외에 매우 큰 memory(기본적으로는 800byte)들을 위해 Large Object Space라는 공간이 따로 존재한다.

세대별 GC는 종류가 매우 다양하다.




만약 Major Heap의 Memory가 Nursery의 memory를 참조하고있다면

참조중이더라도 Nursey의 객체를 해제한다.

이유는 다른 논리적 공간에서 한 참조를 GC가 체크할 수 없기 떄문이다.



Write Barrier


위와같은 이유때문에 Generational GC는 Write Barrier라는 게존재한다.

Wirte Barrier인데 Major heap -> Nursery를 참조하고 있다면 Wirte Barrier에 Nursey에 있는 해당 객체를

미리 write해두고 GC시에 Write Barrier에 있는 memory들은 해제 대상에서 제외한다.

해당방법은 약간의 overhead가 더해진다.



Copy GC


memroy 파편화 현상을 2개의 memory 공간을 사용해서 해결한 방법

memory를 크게 2개로 나누어 관리한다.



SGen 장점


Nursery공간에서만 GC가 빈번하게 일어나기 때문에 비교적 빠르다.

파편화가 적다.(없지는 않다.)


SGen 단점


파편화가 존재한다.

Nuresry, Major Heap중 한 공간만 가득차도 터진다.(그럴일은 거의없다.)








참고

https://proal.tistory.com/72

https://stackoverflow.com/questions/10008953/mono-boehm-vs-sgen-gc

https://hrmrzizon.github.io/2017/04/23/garbage-collector-in-unity/

https://docs.microsoft.com/ko-kr/dotnet/standard/garbage-collection/fundamentals


SGen

https://hrmrzizon.github.io/2017/04/23/garbage-collector-in-unity/


Unity GC 문서

https://blogs.unity3d.com/kr/2018/11/26/feature-preview-incremental-garbage-collection/

'Language > C#' 카테고리의 다른 글

Dictionary  (0) 2019.02.27
ref, out, Tryparse Keyword  (0) 2019.02.26
is, as Keyworkd  (0) 2019.02.26
C#에서의 Get / Set  (0) 2019.02.25
CLR / CLI / JIT / AOT  (0) 2019.02.25