G1GC 자세히 알아보기

G1

java6부터 도입되어 많은 발전을 거쳐온 G1(Garbage First Garbage Collector)java9 부터는 default GC로 채택되어 안정적인 성능을 보여주고 있기 때문에 현재 대부분의 실무 자바 어플리케이션에서는 G1을 사용하고, 이미 잘 알고 계실거라 생각합니다. 따라서 기본적인 개념에대해서는 간단히 알아보고 넘어가도록 하겠습니다.

우선 G1은 기존 CMS GC와 동일하게 오랫동안 살아남은 객체를 분리하여 관리하는 세대 수집기 입니다. 다만, 다른점은 연속되지 않은 메모리 공간 리전(Region)을 단위로 세대들이 구성된 공간을 사용한다는 것 입니다.

1

위와같은 구조로 인해 G1은 다음과 같은 이점이 있습니다.

  • STW(Stop the world)의 시간이 짧다.
  • 대용량 힙에서 사용하기 좋다.

일반적으로 메모리 크기가 커질수록 수집 대상이 많아지는것이기 때문에 STW의 시간은 길어질수 밖에 없습니다. 하지만 G1은 작은 리전들로 구성되어 있기때문에 수집기가 실행될때마다 전체 영역에대한 수집이 아닌 리전단위로 실행 할 수 있어 STW의 발생 시간이 짧게 유지 할 수 있습니다.


G1 작동 원리

G1 가비지 수집은 위에서 보았듯이 리전단위로 이루어지고, 아래와 같은 순서로 작동됩니다.

  1. 초기 마킹 (STW)
  2. 동시 루트 탐색
  3. 동시 마킹
  4. 재마킹 (STW)
  5. 정리 (STW)

초기 마킹 작업은 수집대상 영역 내부에 GC Root / 내부포인터(Internal Pointer)를 얻는 작업을 진행합니다.

동시 루트 탐색 작업은 초기 마킹단계의 서바이버 -> 올드 레퍼런스를 탐색하는 작업을 진행합니다.

동시 마킹 단계에서는 살아있는 객체들을 마킹하는 작업을 진행합니다. 작업 시작전 힙에 존재하는 살아있는 객체들의 스냅샷을 뜨고 마킹 하는 SATB(Snapshot At The Beginning) 알고리즘을 이용합니다.

재마킹 단계에서는 마킹을 마무리하고 죽은 객체들을 정리하는 작업을 진행합니다.

정리 단계에서는 여유공간을 계산하고 재사용 준비를 마친 영역을 식별하는 어카운팅 작업을 진행합니다. 이와 함께 리전의 역 레퍼런스 정보를 담고 있는 Rset을 정리하는 작업도 함께 진행합니다.


Rset (Remembered Set)

2

위에서 잠시 나왔듯이 Rset리전마다 보유하고 있는 외부에서 힙 영역 내부를 참조하는 레퍼런스를 관리하기 위한 자료구조 입니다. 즉 내부 영역을 참조하는 레퍼런스가 존재하는지 찾기위해 모든 메모리 영역을 찾는 대신에 RSET만 조회하여 살아있는 객체를 찾는데 도움이 될 수 있습니다.

Rset을 사용함으로서 외부에서 죽은 객체가 참조하여 실제로는 죽었어야할 객체가 계속해서 살아있는 현상인 부유 가비지를 처리하는데 장점이 있습니다.


통계적 수집

기본적으로 수집 수행은 임의의 정해진 시점이나 점유율의 의해 트리거되는 아닌 수집기가 동작하면서 통계적으로 최적의 수행 점유율 - IHOP(Initiating Heap Occupancy Percent)을 계산해 최적의 수행 방식을 스스로 결정합니다.

IHOP을 결정할때는 마킹에 소요되는 시간과 일반적으로 할당되는 메모리 양을 관찰하여 최적의 IHOP를 자동으로 결정합니다.

-XX:-G1UseAdaptiveIHOP 옵션을 통해 해당기능을 off 할 수 있으며 -XX:InitiatingHeapOccupancyPercent 옵션으로 초기값을 직접 설정 할 수도 있습니다.


거대영역 (Humongous region)

영역의 절반이상을 차지하는 객체는 거대객체(Humongous object)로 취급하여 에덴영역에 할당하지 않고 별도의 거대영역에 할당합니다. 거대영역은 연속된 리전으로 할당된 영역이며 마지막 영역에는 할당되지 않은 공간이 존재 할 수 있는데 남은 공간에 대해서는 타 객체를 할당하는데 사용 할 수 없습니다.

거대영역에 들어온 객체는 Full-GC가 일어나도 압착이 일어나지않아 메모리 단편화를 유발 시킬 수 있어 메모리 공간이 충분한데도 OOM이 발생하는 이유가 될 수도 있습니다. 따라서 거대한 객체를 사용시에는 빠르게 회수될 수 있도록 해주는것이 중요합니다.