본문 바로가기
프로그래밍 언어/C#

[C#] 가비지 컬렉션 (Garbage Collection, GC)

by DDongYeop 2024. 8. 22.
728x90

가비지 컬렉션이란? 

메모리 영역 중 힙 영역의 경우 메모리를 할당하고 어떤 행동을 하지 않는다면 계속 메모리가 올라온 상태로 유지됩니다. 

C와 C++에서는 사용자가 직접 할당 해제를 해줘야 했지만 C# 및 JAVA와 같은 언어에서는 가비지 컬렉션이 존재합니다. 가비지 컬렉션이 직접 할당 해제를 해주어 메모리 관리를 편리하게 합니다. 

한 마디로 정리하자면 메모리 관리를 자동으로 해주는 녀석인 것입니다. 

 

 

가비지란?

reference type의 변수들은 스택 메모리에 주소값을 저장하고, 힙 메모리에 접근하는 방식으로 사용됩니다. 

해당 변수를 사용한 후 함수가 종료되면 지역 변수가 함께 지워지며 스택 메모리에 있는 주소값이 사라지게 된다. 그럼 힙 메모리에 저장된 값은 더 이상 접근할 수 없는 상태가 됩니다. 

여기서 우리는 참조할 수 없게된 객체를 가비지라고 부릅니다. 

 

 

가비지 컬렉션의 세대

가비지 컬렉터는 효율적으로 메모리를 수집하기 위해 객체에게 세대를 매깁니다. 

0세대: 최근에 생성되어 가비지 컬렉팅을 겪은 적이 없는 객체
1세대: 가비지 컬렉팅을 1번 겪었지만 해제 되지 않은 객체
2세대: 가비지 컬렉팅을 2번 이상 겪었지만 해제 되지 않은 객체

 

위와 같이 가비지에게 세대를 매깁니다. 세대가 높아질수록 가비지 컬렉팅을 격고도 생존한 객체로 판단되기에 0세대부터 우선적으로 가비지 컬렉팅을 시행합니다.

즉, 0세대에서 가비지 컬렉팅을 시행했지만 메모리 확보가 불가할 때 1세대를 가비지 컬렉팅 하는 형식입니다.

 

 

가비지 컬렉션의 과정

가비지 컬렉션은 크게 3가지 과정을 거치게 됩니다. 

1. 사용되고 있는 객체들을 연결하는 작업 (Mark)
2. 사용되지 않는 객체들을 식별하는 작업 (Relocate)
3. 필요 없는 객체들을 지우고 살아있는 객체들을 모으는 작업 (Compact)

 

1. Marking 단계 (표시 단계)

 가비지 컬렉션 주기가 시작될 때 가비지 콜렉터는 모든 object를 가비지로 정합니다. 

 이 상태에서 가비지 컬렉터는 루트 목록을 돌면서 각 루트가 참조하는 것을 마킹합니다. 그리고 마킹한 object에서 다른 object를 참조하면 또 마킹합니다. 

 위 과정을 거치며 참조하는 하나의 그래프를 만들게 됩니다. 

출처 - dhsim86.github.io

 

2. Relocating 단계 (재배치 단계)

 GC 루트에 도달 할 수 없는 object를 가비지로 간주합니다. 

 

3. Compactiong 단계 (압축 단계)

 루트 목록에 대한 조사가 끝나면 가비지 컬렉터는 힙을 순회하며 차지했던 비어있는 공간에 인접한 object들을 메모리 복사를 통해 덮어 씌웁니다. 이후 포인터의 위치도 수정합니다. 

 해당 과정으로 깨끗한 상태의 메모리를 얻고 하나의 컬렉션 주기를 이루게 됩니다.

 

 

가비지 컬렉션은 좋기만 할까?

그럼 가비지 컬렉션이 좋은거 아니냐고 생각할 수 있습니다. 메모리 관리를 직접 해주기에 로직쪽에 집중할 수 있고, 직접 관리 하는 것 보단 오류률을 줄일 수 있습니다. 

다만, 가비지 컬렉터가 수행되는 정확한 시점을 알 수 없고, GC가 동장하는 동안 다른 동작을 멈추기에 오버헤드가 발생하는 문제가 생길 수 있습니다. (Stop-The-World) 이로 인하여 GC가 자주 실행되면 소프트웨어의 성능하락 문제가 생길 수 있습니다. 

 

 

가비지를 어떻게 하면 줄일 수 있을까?

1. 객체를 과도하게 할당하지 않기

 너무 많은 object를 사용하면 그만큼 메모리가 금방 차게 되고, GC가 그만큼 많이 발생하게 됩니다. 

 

2. 너무 큰 객체 할당하지 않기

 대형 객체 힙에 대해 이해하면 된다. 

 

3. 복잡한 참조 관계 만들지 않기

 참조 관계가 복잡하다면 메모리 복사만 하는 것이 아닌 모든 메모리를 수정하는 과정을 거치게 됩니다.

 

4. 루트를 많이 만들지 않기

 루트 목록 기반으로 가비지를 찾기에 많지 않다면 루트 목록을 순회하는 시간이 줄어들게 됩니다. 

728x90

'프로그래밍 언어 > C#' 카테고리의 다른 글

[C#] 객체지향 4가지 특성  (0) 2024.09.03
[C#] 메모리의 구조  (0) 2024.08.26

댓글