카테고리 없음

G1GC 동작 과정

yeonirang 2024. 3. 24. 23:07
Serial GC, Parallel GC, Parallel GC, Parallel Old GC, CMS GC, G1GC 들의 개선과 발전 과정을 보면
LIVE하지 못한 객체보다 LIVE 한 객체들의 이동, 복사를 중점으로 둔다.

 

나날이 발전하는 GC들

  • Serial GC 는 가장 단순한 GC로 싱글스레드 1개의 스레드로 다른 GC에 비해 Stop The World 시간이 길다. 실무에서 사용 안한다.
  • Paraller GC 는 Young 영역의 멀티스레드 방식으로 Serial GC보다 STW 시간이 짧다. 자바8의 디폴트 GC
  • Paraller OLD GC는 Old 영역까지 멀티스레드 방식을 사용한 GC이다.
  • CMS GC 는 STW를 줄여보기 위해 Live한 객체를 한번에 찾지 않고 나눠서 찾기로한(마킹하기로한) GC이다.          (Initial Mark,Concurrent Mark,Remark,Concurrent Sweep)
  • G1GC 는 CMS GC를 개선하기 위해 전체 힙이 아닌 영역 단위로 쪼개서 탐색하여 각각의 영역에만 GC한다. 

 

 

GC의 기본 용어에 대해 알아보자.

  • Mark : 접근 가능한 객체를 표시, 마킹
  • Sweep : Mark되지 않은 객체를 제거
  • Compact : Sweep 과정에서 중간 중간의 객체가 삭제되면서 빈공간이 발생한걸 다시 땡겨서 빈자리를 채워줌(압축) 
  • Promotion : Survivor 영역에서 계속 살아남은 객체들이 특정 age 값에 도달하면 Old Generation 영역으로 이동하는 과정

* GC Root에서 시작해서 참조하는 객체를 찾고, 또 그 객체가 참조하는 객체(Rechable)를 찾아가며 Mark 한다.

   Mark 하지 않은, 참조하지 않는 객체(Unreachable한 객체)를 Sweep한다.  

* GC Root 가 될 수 있는 대상 

  JVM 메모리의 Stack 영역에 존재하는 참조변수, Method Area에 해당하는 Static 변수,

  JNI(네이티브스택)에 의해 생성된 객체가 해당된다.

 

일반적인 GC 구조

일반적인 GC구조이다.  

Yong Generation 에 있는 에덴 영역의 객체들이 가득차면 Minor GC가 발생한다.

Unreachable한 객체와 Reachable한 객체를 마킹하고 (Reachable한) live 객체를 survivor region으로 이동되며 S0과 S1중 한 영역은 비어있다.

1. Eden에서살아남은객체가 Survivor 0 으로이동

2. Eden, Survivor 0에서 살아남은객체가 Survivor 1로 이동

3. Eden, Survivor 1에서 살아남은객체가 Survivor 0으로 이동

이런식으로 동작하므로 한 영역은 비어있다. 반복될때마다 살아남을 수록 살아남은 각각의 객체의 age값은 증가하며,

반복되다가 일부 객체의 에이징 임계값이 충족되는 경우(Aging threshold) 이 일부 충족된 객체는 Old Generation 으로 이동한다. 그리고 Old Generation 에 객체가 늘어나면서 비율이 특정 임계값에 도달하면 Major GC가 발생한다. 

 

이제 G1GC 를 알아보자.

- 자바9부터 디폴트로 설정

- 다른 GC와 다르게 힙메모리에 REGION 으로 나누어 관리한다 대략 2048개의 힙영역이 구성된다.(2의 제곱)

- 높은 처리량과 낮은 Stop-The-World(STW) 지향한다.

- G1 (Garbage-First)은 쓰레기가 많을 것으로 예상되는 지역 우선으로 가비지 대상이 된다는 것을 의미한다.

 

G1GC 힙 레이아웃 설명 

Yong Generation 에 해당하는 

빨간색 Eden 에덴영역, 빨간색에 S - Survivor 생존자 영역이 있다.

Old Generation 에 해당하는 영역은 하늘색이다. 

H는 Humongous로 Region 크기의 50%를 초과하는 큰 객체를 저장하기 위한 공간이다. Old 영역에 따로 관리한다.

회색은 Available/Unused, 아직 사용되지 않은 영역이다.

 

G1GC 의 구조

참고

CollectionSet (CSet) 

    CSet는 GC가 실행될 영역(region). CSet내 데이터는 GC 중에 제거(복사/이동)된다.

    Eden, Survivor 및/또는 Old Generation이 될 수 있다. CSet는 JVM 크기에 1% 미만의 영향을 미친다.

Remembered Set (Rset)

    객체의 reference를 가 어느 region에 있는지 알기위해 사용되는 자료구조이다.

    힙에는 지역당 하나의 RSet이 있다. RSet의 전체 설치 공간 영향은 5% 미만이다.

Evacuation - 객체의 복사, 이동을 뜻한다.

 

G1GC의 동작과정을 살펴보자.

 

*Yong Generation

*Minor GC

Minor GC를 보면 기존 GC들과 크게 다르지 않다. 그러나 다른 GC들과 다르게 영역은 연속적일 필요가 없고

멀티쓰레드에서 병렬로 돌아간다.

최소크기는 1MB~32MB 파란색은 Old Generation, 녹색 영역은 Yong Generation 객체를 담고있다.

이 단계는 live한 객체가 Survivor region또는 Old generation으로 이동하는 단계이며,

멀티 스레드로 동작하며 Stop The World 가 발생한다. 

Eden/Survivor 크기는 다음 Minor GC(Young GC)를 위해 계산된다.  

여기서 STW 가 왜 필요할까? 보통 Stop The World 가 발생하는 것만 알지 왜 필요한지는 모른다.
live한 객체의 변수가 복사 이동하더라도 기존에 있던 곳도 참조할 수도 있는 것인데 복사 이동 중에 기존에 있던 곳에 값이 변경되면 일관성이 보장되지 않는다. 심지어 멀티 스레드라면? A스레드의 변수와 B스레드의 변수 값이 달라질 수 있다.

 

Live 한 객체가 Survivor로 이동된 부분을 녹색, 최근 에이징 임계값이 충족되어 승격된 즉 Old 영역에 이동되면 청색으로 표시된다.

g1의 Yong Generation 을 정리하면 아래와 같다.

  • 힙은 여러 영역으로 분할된 단일 메모리 공간이다.
  • Yong Generation 는 연속되지 않은 영역 집합으로 구성되어 이는 필요할 때 크기를 쉽게 조정할 수 있다.
  • Yong Generation 수집은 = Minor GC는 Stop The World 이벤트가 발생한다.
  • Minor GC(Young GC)는 여러 스레드를 사용하여 병렬로 수행된다. (멀티쓰레드) 
  • live 객체는 Survivor영역 또는 Old Generation 으로 복사된다.

*Old Generation

*Major GC(Old GC)

 

XX:InitiatingHeapOccupancyPercent(Old Generation 비율 IHOP)에 지정된 값을 초과하는 순간

G1 수집기는 Old Generation 에 대해 힙에서 아래의 단계를 수행한다. 일부 단계는 Yong Generation Collection의 일부분으로 포함된다. 

(Minor GC가 수행되다가 XX:InitiatingHeapOccupancyPercent(Old Generation 비율 IHOP)에 지정된 값을 초과하는 순간 Major GC가 수행)

 

 

 

초기 마킹 단계

(1) Initial Mark
(Stop the World Event)

Old Generation에 객체들이 참조하는 Survivor 영역이 있는지 찾아 Mark한다.
Young GC 시점에 수행되므로 STW 발생한다.( Survivor영역이 깔끔해야하므로 Survivor 영역에 의존적이다.)

 

Root Region Scanning

루트영역스캔

Initial Mark에서 찾은 Survivor 영역을 스캔하여 Old Generation을 참조하고 있는 객체를 마킹한다.

이는 애플리케이션과 동시에 발생한다. Young GC가 발생하기 전에 완료되어야 한다,

 

 

동시 마킹 단계

(2) Concurrent Marking 

전체 힙에서 live한 객체를(reachable) 찾는다. 이는 애플리케이션과 동시에 발생한다. 애플리케이션과 동시에 발생하는 것은 다음 단계의 STW 시간을 줄이기 위해 마킹한다는 것을 알 수 있다. 이 단계는 Young GC와 함께 수행되며 Young GC 로 인해 중단될 수 있다. 
빈 영역이 있는 경우 X로 표시하고 Remark에서 즉시 제거된다.

 

 

재마킹 단계

 

(3) Remark 
(Stop the World Event)

STW를 발생시키고 힙에 있는 최종적으로 GC 대상에서 제외될 live 객체의 표시를 완료한다. 

해당 단계에서 STW는 변경을 추적하기 위해 필요하다. 이전 동시 마킹 단계에서의 부정확한 마킹을 마무리하고, 참조가 변경된 객체들에 대해서 새롭게 마킹을 할 수 있다.


CMS 수집기에서 사용된 것보다 훨씬 빠른 SATB(snapshot-at-the-beginning)라는 알고리즘을 사용한다.

 

복사 및 정리 단계

(4) Copying/Cleanup
(Stop the World Event and Concurrent) 

Copying : 
애플레키션을 멈추고(STW) 해당 영역의 live 한 객체를 다른 영역으로 Evacuation(이동/복사) 시킨다. 

Minor GC(Young GC) 와 Magor GC가 같이 수행된다.

Cleanup : 애플리케이션을 멈추고(STW) live 객체가 가장 적은 영역순으로 미사용 객체 제거 수행한다. Rset 도 정리한다. 이후 STW를 끝내고, 앞선 GC 과정에서 완전히 비워진 Region 을 Freelist에 추가하여 재사용될 수 있게 한다.(Concurrent)


* FREE LIST란 JVM 힙의 사용가능한 영역 크기를 추적하기 위해 사용되는 자료구조

복사 및 정리 이후

(5) After Copying/Cleanup
(Stop the World Event)

 

live 객체가 새로운 영역에 이동되어 Compaction된 것을 확인 할 수 있다.
*Compaction(압축 빈공간정리)

 

 

 

 

아래는

G1가비지 수집기 수집 개요도 이다.

위 단계들을 2단계로 번갈아 가면서 일어난다고 표현할 수도 있다. 

Young-only 단계

Eden 영역이 가득차면 왼쪽 첫번째 작은 파란원부터 일반적인 Young GC를 수행한다.(Normal Young Collection)

각 영역별 생존 객체들은 Survival 영역으로 이동하고, age가 임계값 이상이 되면 old 영역으로 이동된다. 

Old Generation의 점유율이 특정 임계값에 도달하면 Nomal Young Collection에서 Concurrent Start Young Collection으로 전환된다.

그림에 Old gen occupancy exceeds threshold는 임계값이 도달했다는 것을 알 수 있고, Concurrent Start 병행 수행을 시작한다. 

Major GC의 Initail Mark 부터(STW) 시작되는데 Young GC시점에 수행되므로 파란색 원이 크다. (혹시 아니면 피드백 부탁드립니다)

마킹이 완전히 발생하기 전까지 애플리케이션 스레드와 Young GC, 마킹 프로세스가 병행 수행되다가 Remark 시점에 큰 STW가 발생한다. 

Remark 시점에는 비어있는 영역 회수하고, 마킹을 최종화 하고 클래스 언로딩한다.

Remark 와 Cleanup 사이에 G1 은 Cleanup 단계에서 최종화될 선택된 Old Generation 의  빈 공간을 계산한다. 

Cleanup  Space Reclamation 단계인 공간 재확보 발생 여부를 결정한다. 

여기서의 Cleanup 은 Major GC의 클린업이 아니다. 공간 재확보 발생 여부를 결정한다. 

지워야될 객체가 없다면 Space Reclamation 단계를 생략할 것이고, 만약 지워야될 객체가 있어서 Space Reclamation 단계가 동작한다.

=> 이부분이 헷갈리는게 어떤 참고자료에는 major gc가 Remark한것을 지울 객체를 제거한다고하고

공간재확보단계에서 mixed gc를 한다는 자료도 있고

 

Space Reclamation 단계(공간 회수 단계) 

이 단계는 multiple Mixed collections으로 구성되며,

Young Generation 영역뿐만 아니라 Old Generation 영역의 일부를 대상으로 객체들 메모리를 회수한다. (Evacuation)

즉, Old 영역의 Garbage까지 수집하는 Minor GC 방식의 Mixed GC 방식이 수행된다.

Mixed GC를 수행하는 단계이기 때문에 young-only 단계에서 계산한 결과를 가지고 Collection Set에 포함될 old영역을 선출하고 gc대상 영역을 저장한다.

더 많은  Old Generation 영역을 더 이동하는것이 작업효율이 떨어진다고 판단될 때 종료된다.

 

Space Reclamation 후에 GC 는 Young Only 단계부터 다시 시작한다. 만약 응용프로그램이 모든 메모리를 사용한다면 다른 GC 들과 마찬가지로 Full GC 가 수행된다.

 

 

 

 

피드백 제공해주시면 감사합니다.

 

참고

https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html

 

Getting Started with the G1 Garbage Collector

Java Overview Java is a programming language and computing platform first released by Sun Microsystems in 1995. It is the underlying technology that powers Java programs including utilities, games, and business applications. Java runs on more than 850 mill

www.oracle.com

https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector.html#GUID-1CDEB6B6-9463-4998-815D-05E095BFBD0F

 

HotSpot Virtual Machine Garbage Collection Tuning Guide

 

docs.oracle.com

https://programmer7895.tistory.com/86#1.%20**%EC%B4%88%EA%B8%B0%20%ED%91%9C%EC%8B%9C(Initial%20Mark)**-1  

https://imp51.tistory.com/entry/G1-GC-Garbage-First-Garbage-Collector-Tuning  

https://steady-coding.tistory.com/590

https://assets.velcdn.com/@phj5075/g1gc  

https://velog.io/@mu1616/%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98-GC