Post

GC와 G1GC

GC(가비지 컬렉션)와 G1GC(가비지 우선 수집기)가 무엇인지 알아보고, 어떻게 동작하는지 이해해보자.

GC와 G1GC

GC(가비지 컬렉션)

GC란?

GC
자바의 메모리 관리 방법 중의 하나이다.
JVM(자바 가상 머신)의 Heap 영역에서 동적으로 할당했던 메모리 중, 사용되지 않는 메모리 객체(garbage)를 모아 주기적으로 제거하는 프로세스이다.
java 외에도 파이썬, 자바스크립트, Go 언어 등에서 가비지 컬렉션이 기본으로 내장되어있다.
C,C++는 개발자가 메모리를 직접 관리해야 했는데, GC가 있으면 개발자는 개발에만 집중할 수 있게 되었다.
개발자가 메모리 제어를 하지 않아 정확하게 관리되는 시점을 모르고, 개발자가 직접 제어할 수 없으며, GC 동작시에는 다른 동작을 멈추기 떄문에 오버헤드가 발생되는 문제가 있다.
필요 없게 된 메모리 객체(garbage)란?
더 이상 참조되지 않는 객체를 의미한다.

GC는 garbage 판단의 기준을 도달능력으로 해, 객체에 참조값이 있다면 Reachable으로, 없다면 Unreachable으로 구분한다. Unreachable으로 구분된 내용은 GC의 대상이다.

대표 예시

  • 컬렉션에서 제거된 객체
  • 참조가 끊어진 객체
  • 메서드 실행 후 사라지는 지역 변수 객체
핵심 목표
Stop-the-World 시간을 줄이면서도 메모리를 효율적으로 관리하기
최대한 성능을 유지하면서 불필요한 객체를 정리하기
Stop-the-World 시간이란?
GC가 실행될 때, JVM이 애플리케이션 실행을 일시적으로 멈추고 GC 작업을 수행하는 시간을 의미한다.

GC가 작동하는 동안 GC와 관련되지 않은 내용들은 중단되어 서비스 이용에 차질이 생길 수 있다. 이 시간은 최대한 줄이는 것이 좋다.

동작원리

GC는 Mark-Sweep라는 알고리즘을 이용해, ReachableUnreachable으로 구분한다.

Mark-Sweep

루트를 기준으로 그래프 순회를 통해 해당 객체에 접근을 할 수 있는지 없는지 판단하는 알고리즘이다.

  1. Mark 과정
    먼저 GC Root로부터 그래프 순회(DFS 또는 BFS 방식)를 통해 연결된 객체들을 탐색한다.
    각 어떤 객체를 참조하고 있는지 찾아서 연결된 객체는 연결되어있다고 마킹한다.
  2. Sweep 과정
    참조하고 있지 않은 객체 즉 Unreachable 객체들을 Heap에서 제거한다.
  3. Compact 과정
    Sweep 후에 살아남은 객체들을 Heap의 한쪽으로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축한다. (가비지 컬렉터 종류에 따라 하지 않는 경우도 있음)

힙(heap) 메모리 구조

힙(heap)
동적으로 레퍼런스 데이터가 저장되는 공간이다.
가비지 컬렉션에 대상이 되는 공간이다.
보다 효율적인 메모리 관리를 위해 객체의 생명 주기에 따라, Young GenerationOld Generation으로 나뉘어 관리된다.
객체의 생명 주기
객체가 생성되고 사용되다가 메모리에서 해제되기까지의 과정을 의미한다.
대부분 일회성으로 메모리에 오랫동안 남아있는 경우는 드물다.
Young Generation
새로운 객체들이 할당되는 영역이다.
내부는 Eden, Survivor(From), Survivor(To) 영역으로 나뉜다.
새로운 객체는 Eden에서 시작하며, 살아남으면 Survivor로 이동,
Young Generation영역에서 수행되는 GC를 Minor GC라고 한다.
Old Generation
Young Generation을 여러 번 거쳐 살아남은 객체들이 이동하는 영역이다.
장기간 참조되는 객체들이 저장된다.
Young Generation영역에서 수행되는 GC를 Mjor GC라고 한다.

GC의 동작 과정

Minor GC
Eden영역을 대상으로, Eden영역이 가득 차면 실행된다.
살아남은 객체들은 Survivor영역으로 이동시킨다.
일정 횟수 이상 살아남은 객체는 Old Generation으로 이동시킨다.
속도가 빠르다.
Major GC
Old Generation영역을 대상으로, Old Generation영역이 가득 차면 실행된다.
Minor GC보다 느리며, 실행 시 애플리케이션을 멈추는 시간이 길어질 수 있다.
Old Generation은 객체 수명이 길어서 정리할 때 성능 부담이 크기 때문에, 최적화하는 방식이 중요하다.
Full GC (Heap 전체 대상)
Heap 전체를 검사하고, 사용되지 않는 객체를 정리하는 GC이다.
Old Generation뿐만 아니라 Young Generation까지 포함한 전체 힙(heap)을 대상으로 수행된다.
가장 느린 GC이며, Stop-the-World 시간이 가장 길어 성능에 영향을 크게 미친다.
자주 발생하면 애플리케이션 성능이 심각하게 저하될 수 있어, 튜닝시 발생을 최소화하는 것이 중요하다.

G1GC(가비지 우선 수집기)

G1GC란?

G1GC
GC의 알고리즘 중 하나로 힙(heap)을 고정된 크기의 작은 블록(Region)으로 나눠 정리하는 방식의 알고리즘이다.
Full GC를 최소화하여 Stop-the-World 시간을 줄이는 방식이다.
대용량 애플리케이션(Heap 크기가 4GB 이상)에서 효과적이다.
Java 9 이후 기본 GC로 사용된다.
특징
힙을 Region으로 나눈다. 기존 GC는 세대별(Generation-based)로 관리했지만, G1GC는 고정 크기의 Region 단위로 관리한다. 그렇다고 Young/Old이 사라진 것이 아닌, Eden / Survivor / Old Generation이 단일 블록이 아닌 여러 개의 Region으로 이루어질 수 있는 것이다.
가비지가 많은 Region을 먼저 정리하는 알고리즘이다.
Stop-the-World 시간을 일정한 목표 값으로 조정할 수 있고, JVM은 이 목표에 맞게 Region 크기 및 GC 실행 주기를 자동으로 조정한다.
Mixed GCOld Generation이 꽉 차서 Major GC가 실행되는 것을 방지하는 역할이다.
일반적으로는 Region 단위로 관리하지만, 대형 객체는 Humongous Region에 저장한다.

Region의 크기 JVM이 자동으로 조정하는 범위(1MB ~ 32MB) 내의 크기로 결정된다.

Humongous Region
일반 Region보다 크고, Region 크기의 50%를 초과하는 대형 객체를 저장하는 특수한 Region

동작원리

Young GC
Eden이 가득 차면 Young GC 실행한다.
Eden의 살아남은 객체 → Survivor Region으로 이동한다.
일정 횟수 이상 살아남으면 Old Generation으로 이동한다.
Mixed GC
G1GC에만 존재하는 특수한 GC이다.
Young GC 수행시, 일부 Old Generation Region도 함께 정리하는 방식이다. Old Generation이 가득 차기 전에 Mixed GC를 실행하여 일부 Old Generation를 정리함으로써 Full GC 발생할 가능성을 낮춘다.
Concurrent GC
애플리케이션 실행 중에 GC가 백그라운드에서 실행할 수 있다. 일부 GC 작업(Mark 단계와 Cleanup 단계)을 애플리케이션 실행과 병렬로 수행하여, 애플리케이션 멈춤 시간을 줄이는 방식으로 동작한다.
Full GC
힙(Heap)이 꽉 차고, Mixed GC로 해결되지 않을 경우 Full GC 실행한다.
기존 GC 대비 Full GC 발생 확률이 적다.
This post is licensed under CC BY 4.0 by the author.