본문 바로가기

CS study/java

GC - Major, Minor 가비지 컬렉션에 대한 정리 (24.06.05)

개념

Minor GC와 Major GC는 JVM의 가비지 컬렉션에서 중요한 역할을 하는 두 가지 유형의 가비지 컬렉션 이벤트이다. 이 두 가지 GC의 차이점과 동작 방식을 자세히 설명하겠다.

Minor GC

개요:

  • Minor GC는 Young Generation에서 발생하는 가비지 컬렉션이다. Young Generation은 Eden 영역과 두 개의 Survivor 영역(S0, S1)으로 구성된다.

동작 방식:

  1. Eden 영역이 가득 찰 때 발생:
    • 새로운 객체가 주로 Eden 영역에 할당된다. Eden 영역이 가득 차면 Minor GC가 발생한다.
  2. 생존 객체 이동:
    • Minor GC 동안, Eden 영역의 모든 객체가 검사된다. 살아남은 객체는 Survivor 영역(S0 또는 S1)으로 이동한다.
    • 하나의 Survivor 영역이 가득 차면 다른 Survivor 영역으로 객체가 이동된다.
    • 여러 번의 Minor GC를 통해 Survivor 영역에 남아있는 객체가 Old Generation으로 승격된다.
  3. 빠른 수행 시간:
    • Minor GC는 상대적으로 빠르게 수행된다. Young Generation은 크기가 작기 때문에 컬렉션 작업이 빠르게 완료된다.

영향:

  • Minor GC는 Young Generation의 객체를 정리하는 과정으로, 응답 시간에 짧은 영향을 미칠 수 있다. 그러나 이 영향은 대부분의 경우 비교적 적다.

Major GC (또는 Full GC)

개요:

  • Major GC는 Old Generation에서 발생하는 가비지 컬렉션이다. Old Generation은 장기적으로 살아남는 객체를 저장하는 영역이다.

동작 방식:

  1. Old Generation이 가득 찰 때 발생:
    • Old Generation의 메모리가 부족할 때 Major GC가 발생한다.
  2. 전체 힙 검사:
    • Major GC는 Young Generation뿐만 아니라 Old Generation 전체를 검사한다. 이 과정에서 모든 살아있는 객체를 식별하고 가비지를 정리한다.
  3. 상대적으로 긴 수행 시간:
    • Major GC는 전체 힙을 검사하므로 시간이 더 오래 걸린다. 이로 인해 애플리케이션의 일시적인 중단이 발생할 수 있다.

영향:

  • Major GC는 애플리케이션 성능에 더 큰 영향을 미칠 수 있다. 특히 Old Generation의 크기와 객체 수가 많을수록 GC 수행 시간이 길어질 수 있다.
  • Major GC가 자주 발생하면 성능 저하를 유발할 수 있으므로, 메모리 관리와 GC 튜닝이 중요하다.

GC 튜닝

GC 성능을 최적화하기 위해 다양한 JVM 옵션을 사용하여 GC 동작을 조정할 수 있다. 예를 들어, 다음과 같은 옵션을 사용하여 GC 로그를 기록하고, GC 정책을 조정할 수 있다:

  • GC 로그 기록:
  • bash코드 복사 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log
  • GC 정책 조정:
    • G1 GC 사용:
    • bash코드 복사 -XX:+UseG1GC
    • CMS (Concurrent Mark-Sweep) GC 사용:
    • bash코드 복사 -XX:+UseConcMarkSweepGC
    • Parallel GC 사용:
    • bash코드 복사 -XX:+UseParallelGC

GC 튜닝은 애플리케이션의 특성과 메모리 사용 패턴에 따라 달라질 수 있으며, 적절한 설정을 통해 성능을 최적화할 수 있다.

성능 최적화

가비지 컬렉션(GC)은 JVM의 메모리 관리에서 중요한 역할을 한다. Minor GC와 Major GC 각각의 최적화 방법과 성능 영향을 줄이는 방법을 설명하겠다.

1. Minor GC 최적화

Minor GC는 Eden 영역에서 발생하며, 이 영역의 객체들이 대부분 단명하는 특성을 이용한다. Minor GC는 상대적으로 빠르게 수행되지만, 빈번하게 발생하면 성능에 영향을 미칠 수 있다. 이를 최적화하는 방법은 다음과 같다:

  1. Eden 영역 크기 조정:
    • Eden 영역의 크기를 적절히 조정하면 Minor GC의 빈도를 줄일 수 있다. 너무 작으면 Minor GC가 자주 발생하고, 너무 크면 Old Generation으로의 승격이 지연되어 Major GC가 자주 발생할 수 있다.
    • JVM 옵션 예시:
    • bash코드 복사 -XX:NewSize=<size> -XX:MaxNewSize=<size>
  2. 생성되는 객체 수 줄이기:
    • 불필요한 객체 생성을 최소화하고, 객체의 재사용을 늘려야 한다. 예를 들어, 객체 풀링(Object Pooling)을 사용하여 객체를 재사용할 수 있다.
  3. GC 로그 분석:
    • GC 로그를 분석하여 Minor GC의 빈도와 소요 시간을 확인하고, 이에 따라 적절한 조정을 한다.
    • JVM 옵션 예시:
    • bash코드 복사 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log

2. Major GC 최적화

Major GC는 Old Generation에서 발생하며, 수행 중 모든 쓰레드가 멈추는 Stop-the-World(STW) 이벤트를 발생시킨다. 이는 성능에 치명적인 영향을 줄 수 있다. Major GC의 최적화 방법은 다음과 같다:

  1. Old Generation 크기 조정:
    • Old Generation의 크기를 조정하여 Major GC가 발생하는 빈도를 줄일 수 있다. 이를 통해 STW 이벤트를 최소화할 수 있다.
    • JVM 옵션 예시:
    • bash코드 복사 -XX:OldSize=<size> -XX:MaxOldSize=<size>
  2. GC 정책 선택:
    • 다양한 GC 정책을 사용하여 성능을 최적화할 수 있다. G1 GC, CMS GC, Parallel GC 등의 정책을 상황에 맞게 선택한다.
    • G1 GC (Garbage-First Garbage Collector):
    • bash코드 복사 -XX:+UseG1GC
    • CMS GC (Concurrent Mark-Sweep GC):
    • bash코드 복사 -XX:+UseConcMarkSweepGC
    • Parallel GC:
    • bash코드 복사 -XX:+UseParallelGC
  3. GC 튜닝:
    • 각 GC 정책에 맞는 튜닝 옵션을 설정하여 성능을 최적화한다. 예를 들어, G1 GC의 경우 다음과 같은 옵션을 사용할 수 있다:
    • bash코드 복사 -XX:MaxGCPauseMillis=<time_in_ms> -XX:InitiatingHeapOccupancyPercent=<percentage>
  4. 메모리 할당 패턴 최적화:
    • 객체의 생명주기를 분석하여 메모리 할당 패턴을 최적화한다. 예를 들어, 불필요하게 오래 생존하는 객체를 줄이도록 코드 구조를 개선한다.
  5. GC 로그 분석 및 모니터링:
    • GC 로그를 지속적으로 분석하여 Major GC의 빈도와 소요 시간을 파악하고, 이에 따라 메모리 설정을 조정한다.

결론

  • Minor GC는 주기적으로 발생하지만, Eden 영역의 크기 조정과 객체 생성 패턴 최적화를 통해 빈도를 줄일 수 있다.
  • Major GC는 Stop-the-World 이벤트를 발생시키므로, GC 정책 선택과 Old Generation 크기 조정, 메모리 할당 패턴 최적화를 통해 성능 영향을 최소화할 수 있다.

이를 통해 GC로 인한 성능 문제를 완화할 수 있다. GC 로그 분석과 모니터링은 최적화 과정에서 매우 중요한 도구이다.