본문 바로가기

카테고리 없음

#23 GC(Garbage Collector)

가비지 컬렉션(Garbage Collection, GC)은 컴퓨터 프로그래밍에서 메모리 관리를 자동화하는 메커니즘이다. GC의 주요 목적은 프로그래머가 메모리 할당과 해제를 수동으로 관리하지 않아도 되도록 하여 메모리 누수(memory leak)와 같은 오류를 방지하는 것이다. 

 

 

가비지(Garbage)란?

가비지란 더 이상 프로그램에서 참조하지 않는 객체들을 의미한다. 이러한 객체들은 메모리에 남아있지만, 어떤 변수도 이를 참조하지 않기 때문에 쓸모가 없고 메모리만 차지하게 된다.

 

 

가비지 컬렉션이란?

가비지 컬렉션은 이러한 쓸모없는 객체들을 자동으로 식별하고 메모리에서 제거하는 과정이다. 이를 통해 사용 가능한 메모리를 확보하고 프로그램의 효율성을 높인다.

 

 

 

 

GC의 작동 원리

GC는 다양한 알고리즘을 통해 메모리 관리를 수행한다. 대표적인 알고리즘에는 참조 카운팅(reference counting), 마크-앤-스윕(mark-and-sweep), 복사(copying), 마크-컴팩트(mark-compact) 등이 있다.

 

 

참조 카운팅 (Reference Counting)

참조 카운팅은 각 객체에 대해 참조 횟수를 유지하는 방식이다. 객체가 생성되면 참조 카운터가 1이 되고, 다른 객체가 이를 참조할 때마다 카운터가 증가한다. 반대로 참조가 해제되면 카운터가 감소한다. 카운터가 0이 되면 해당 객체는 가비지로 간주되어 메모리에서 해제된다.

 

장점:

  • 구현이 간단하고, 객체가 참조되지 않는 순간 바로 메모리를 해제할 수 있다.

단점:

  • 순환 참조(circular reference) 문제를 해결하지 못한다.

 

 

마크-앤-스윕 (Mark-and-Sweep)

마크-앤-스윕 알고리즘은 두 단계로 이루어진다.

  1. 마크 단계 (Mark Phase): GC가 루트 객체(root object)에서 시작하여 도달할 수 있는 모든 객체를 마킹(marking)한다.
  2. 스윕 단계 (Sweep Phase): 마킹되지 않은 객체들을 메모리에서 해제한다.

장점:

  • 순환 참조 문제를 해결할 수 있다.

단점:

  • 실행 중 프로그램의 일시 정지를 유발할 수 있다.
  • 메모리 파편화(fragmentation)가 발생할 수 있다.

 

 

 

복사 (Copying)

복사 알고리즘은 메모리를 두 개의 반으로 나누어 사용한다.

  1. 활성 영역(active region): 현재 프로그램이 사용하는 메모리 공간이다.
  2. 비활성 영역(inactive region): 비어있는 메모리 공간이다.

 

GC는 활성 영역에서 사용 중인 객체들을 비활성 영역으로 복사하고, 남아있는 객체는 모두 가비지로 간주되어 해제한다. 복사가 완료되면 두 영역의 역할이 전환된다.

장점:

  • 메모리 파편화를 방지할 수 있다.
  • 복사 작업이 빠르다.

단점:

  • 메모리 사용 효율성이 떨어질 수 있다.

 

 

 

마크-컴팩트 (Mark-Compact)

마크-컴팩트 알고리즘은 마크-앤-스윕과 유사하지만, 추가적으로 메모리 파편화를 방지한다.

  1. 마크 단계: 마크-앤-스윕과 동일하게 루트 객체에서 시작하여 도달할 수 있는 모든 객체를 마킹한다.
  2. 컴팩트 단계 (Compact Phase): 살아있는 객체들을 메모리의 한쪽으로 이동시켜 연속된 공간을 확보한다.

장점:

  • 메모리 파편화를 방지할 수 있다.

단점:

  • 객체 이동으로 인한 오버헤드가 발생할 수 있다.

 

 

현대적인 GC의 특징

현대적인 GC는 위의 기본 알고리즘을 결합하여 성능을 최적화하고 다양한 상황에 대응한다. 예를 들어, Java의 HotSpot VM에는 여러 GC 알고리즘이 있으며, 상황에 따라 다르게 작동한다. 대표적인 GC 모드는 다음과 같다:

  • Serial GC: 단일 스레드로 작동하는 간단한 GC다. 작은 메모리 공간에서 효율적이다.
  • Parallel GC: 여러 스레드를 사용하여 병렬로 가비지 컬렉션을 수행한다. 다중 프로세서 환경에서 성능이 우수하다.
  • CMS (Concurrent Mark-Sweep) GC: 마크 단계와 스윕 단계를 병렬로 수행하여 응답성을 높인다.
  • G1 (Garbage-First) GC: 힙을 여러 영역으로 나누고, 가장 많은 가비지를 포함하는 영역을 우선적으로 수집한다. 예측 가능한 짧은 멈춤 시간을 제공한다.

 

 

GC 튜닝

GC는 자동으로 작동하지만, 특정 애플리케이션의 요구사항에 맞게 튜닝이 필요할 수 있다. Java VM에서는 다음과 같은 옵션을 통해 GC 동작을 조정할 수 있다:

  • -XX:+UseSerialGC: Serial GC를 사용한다.
  • -XX:+UseParallelGC: Parallel GC를 사용한다.
  • -XX:+UseConcMarkSweepGC: CMS GC를 사용한다.
  • -XX:+UseG1GC: G1 GC를 사용한다.
  • -Xms 및 -Xmx 옵션: 힙 메모리 크기를 조정한다.

 

GC는 현대 프로그래밍 언어에서 중요한 역할을 하는 메모리 관리 기법이다. 다양한 알고리즘을 통해 자동으로 메모리를 관리하여 프로그래머의 부담을 줄이고, 프로그램의 안정성과 효율성을 높인다. 각 알고리즘은 장단점이 있으며, 특정 상황에 맞게 선택하고 조정할 수 있다. GC에 대한 깊은 이해는 성능 최적화와 메모리 관리에 큰 도움이 된다.