2 min to read
C# Garbage Collector 2
-
닷넷의 GC의 최적화 기법 중 대표적인 것의 세대별 가비지 컬렉션이다. 오늘은 이 세대별 가비지 컬렉션이 어떻게 동작을 하는지 알아본다.
-
세대별 가비지 컬렉션은
힙
상의 객체의 생존 시간에 따라 세대별로 구분하여 GC를 수행하는 것을 말한다. -
0세대(GC 0)는 최근 생성된 객체이고, 1세대(GC 1)는 1회의 GC 동안 남아있는 객체이며 2세대(GC 2)는 2회 이상의 GC 동안 남아있는 객체를 의미한다.
-
닷넷의 GC는 기본적으로 0세대에 대해 GC를 수행하며 1,2세대는 특정 조건에 해당되면 수행한다.
-
0세대에 대해 집중적으로 GC를 수행하면 GC의 성능과 효율을 올릴 수 있는데 근거는 다음과 같다.
- 최근 생성된 객체는 생명주기가 짧다.
- 오래된 객체일수록 생명주기는 길다.
- 최근에 생성된 객체들끼리는 서로 연관성이 높고 비슷한 시점에 엑세스 된다.
- 일부분의 힙을 GC하는 것이 전체 GC하는 것보다 빠르다.
GC 0
-
GC 0의 동작 방식은 다음과 같다. 기본적으로 객체를 최초 생성하게되면 항상 0세대가 된다. 이후 CLR에 의해 GC가 발생하면 0세대에 대해서만 GC가 이루어진다.
-
0세대에 대하여 GC가 이루어지면 두 번째와 같은 힙이 구성이 되며, 처음 힙에서의 객체 A는 사라지게 되고 B,C는 1세대로 승급하게 된다.
-
이후 추가적으로 객체가 할당이 되면 해당 객체들은 0세대로 생성이되고(세 번째 힙 구성) 다시 GC가 이루어지면 객체 E는 사라지고 나머지 D,F는 1세대로 승급하게 된다.
-
하지만 네 번째 힙 구성과 같이 객체 B는 GC대상이지만 사라지지 않는데, 0세대에 대해서만 GC가 이루어졌기 때문에 1세대의 B는 GC되지 않고 남아있는 것이다.
GC 1
-
시간이 지남에 따라 1세대의 힙 크기가 점차 커지게 되는데, 즉 힙의 사용 가능한 메모리가 줄어든다는 것이다.
-
CLR 내부에서 결정된 특정 조건에 도달하면 GC는 0세대와 1세대에 대해서 GC를 수행하게 된다. 0세대에 대해서만 GC가 이루어지는 것을
GC 0
이라하고 0,1세대 같이 이루어지는 것을GC 1
이라 칭한다. -
GC 1에서 살아남은 객체는 1세대 객체는 2세대로 승급하며 또한 0세대 객체는 1세대로 승급한다.
-
다음 사진은
GC 0
에서 부터 이어지는 힙 상의 객체 그림이며, GC 1이 이루어지면 객체 B,D는 사라지게 되고 C,F는 2세대로 승급하게 된다. 그리고 H는 1세대로 승급하게되며 두 번째와 같은 힙이 구성된다. -
새로운 객체 I,J가 할당되고, 다시 GC 1이 이루어진다고 가정하면 (실제로는 GC 1이 연속으로 발생하는 경우는 매우 희박하다.) 마지막과 같이 객체 H는 2세대로 승급을 하고 I는 1세대로 승급을 한다. 더불어 객체 F는 더 이상 사용을 하지 않지만 GC 1을 수행했기 때문에 GC의 대상이 아니다.
GC 2
-
2세대 객체들은 GC가 2세대 GC를 수행하지 않는 한 힙에 계속 존재한다.
-
GC 2도 GC 1과 마찬가지로 GC 1을 수행해도 힙 상의 메모리가 부족할 것 같은 상황에서 발생하며 2세대 GC는 0세대와 1세대를 포함하며 수행하기 때문에 GC 2 혹은 Full GC라고 한다.
-
Full GC는 전체 가비지 컬렉션을 의미하며 마지막 그림에서 GC 2를 수행하게 되면 객체 I는 2세대로 승급하고 C,H는 2세대 이상은 존재하지 않기 때문에 2세대로 남고, F는 사라지게 될것이다.