ZGC
1 ZGC
- The Z Garbage Collector
- JDK 11에서 처 음 선보였고 JDK 15부터 Production Ready 상태
1.1 ZGC의 목표
JEP333에서 설정한 목표
- GC pause time이 10ms를 초과하지 않기
- 작은 사이즈의 힙(a few hundreds of megabytes)부터 큰 사이즈의 힙(many terabytes)까지 지원하기
- G1 gc와 비교하여 throughput 저하를 최대 15%까지만 허용하기
- low-latency을 중시하기 때문에 그만큼 throughput이 희생된다.
추가적인 목표
- 쉬운 튜닝
- The Java ZGC is easy to use and require minimal configuration.
JEP: JDK Enhancement Proposals
1.2 ZGC란?
ZGC is a scalable low-latency garbage collector
low latency
- 최대 1ms의 pause times
- JEP 333에서는 10ms이하지만 JEP 333의 작성자 Per Liden의 영상에서는 1ms이하로 설정
- ZGC - The Future of Low-Latency Garbage Collection Is Here 여기 참고
- JDK 16이후부터 1ms 이하로 목표 설정
- Erik Österlund — Concurrent thread-stack processing in the Z Garbage Collector 참고
scalable
- Pause times do not increase with root-set size
- ZGC pause O(1)
- 최소 힙 사이즈 8MB
- 최대 힙 사이즈 16TB
- JEP 377: ZGC: A Scalable Low-Latency Garbage Collector (Production)를 통해서 4TB에서 16TB로 상승했다.
root set
- root set으로부터 시작한 참조 사슬에 속한 객체들은 reachable 객체이고, 이 참조 사슬과 무관한 객체들이 unreachable 객체로 GC 대상이다
Ease of use
- The Java ZGC is easy to use and require minimal configuration.
1.3 ZGC의 특징 요약
Concurrent
- 자바 쓰레드가 실행되는 동시에 GC 쓰레드가 백그라운드에서 실행된다.
- 동기화를 위한 짧은 STW를 제외하고 거의 모든 GC 작업(marking, heap defragmentation)이 자바 쓰레드와 동시에 진행된다.
Region-based
- 힙은 3가지 종류의 특정 사이즈의 regions들로 구성된다.
Compacting
- 메모리 단편화를 막기위해 주기적으로 살아있는 객체들을 한 region에서 다른 region으로 옮긴 다.
Single Generation(Non-generational)
- 전체 힙을 대상으로 GC cycle이 진행된다.
- 기존의 GC 처럼 young generation과 old generation의 구분이 없다.
- Generational ZGC는 현재 진행중에 있다.
- JEP 439: Generational ZGC
Using colored pointers
Using load barriers
NUMA-aware
1.4 GC 선정 기준
1.4.1 Maximum Pause-Time
- 레퍼런스
- Pause-Time이란 garbage collector가 애플리케이션을 멈추고 가비지를 수집하는 시간이다.
- Maximum Pause-Time은 Pause-Time의 최대치를 제한하는 목적이다.
- Maximum Pause-Time은
-XX:MaxGCPauseMillis=<nnn>옵션으로 설정할 수 있다.- 이 옵션을 설정한다고 해서 pause-time 목표가 무조건 달성되는 것은 아니다.
- GC는 해당 목표를 달성하기 위해 힙의 사이즈와 관련된 파라미터를 조절한다.
- 기본 Maximum Pause-Time은 gc의 종류마다 다르다.
- 이러한 조절이 gc가 더 많이 발생하게 할 수도 있고 throughput을 저하시킬수도 있다.
1.4.2 Throughput Goal
- 가비지를 수집하는 시간과 애플리케이션 동작하는 시간의 비율이다.
-XX:GCTimeRatio=nnn옵션으로 비율을 지정할 수 있다.- 가비지 수집 시간과 애플리케이션이 동작하는 비율이 1 / (1 + nnn)이라는 의미다.
- 예를 들어
-XX:GCTimeRatio=19로 옵션을 지정하면 비율은 1/20으로 애플리케이션 동작 시간의 5%만 가비지 수집 시간으로 사용한다.
1.4.3 Footprint
- throughput과 maximum pause-time 목표가 모두 달성되면 gc는 둘 중 하나의 목표가 충족되지 않을 때까지 힙의 사이즈를 줄인다.
- 주로 throughput이 총족되지 못한다.
- 최소 힙 사이즈를 설정하는 옵션:
-Xms=<nnn> - 최대 힙 사이즈를 설정하는 옵션:
-Xmx=<mmm>
1.4.4 비교
- 여러 GC들의 목표를 비교해보자
- 모든 기준을 만족시키는 하나의 GC는 없기 때문에 상황에 맞게 GC를 선택해야한다.



출처: Java’s Highly Scalable Low-Latency Garbage Collector : ZGC
2 성능
2.1 G1과 비교
Thoughput과 Lataency 비교

- Thoughput은 G1이 더 좋다.
- Lataency는 ZGC가 더 좋다.
GC Pause time 비교

- ZGC는 1ms 이하라 보이지도 않는다.

- 마이크로 세컨으로 단위 변경 후
2.2 JDK 버전과 성능 향상



2.3 Non-generation과 Generational ZGC 성능 비교
- Generational ZGC는 아직 개발 중이지만 먼저 Non-generation ZGC와 성능 비교를 해보자.
메모리 사용량

성능
- Generational ZGC가 메모리를 덜 쓰지만 성능이 더 잘나옴

CPU 사용량

3 사용하기
Java를 실행할 때 아래의 옵션을 주면 ZGC를 사용할 수 있다.
-XX:+UseZGC
JDK 11에서 JDK 15 까지는 아래의 옵션이 추가적으로 필요하다.
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
4 Tuning
- ZGC의 목표는 쉬운 튜닝이다 따라서 Heap Size 튜닝만을 권장하고 있다.
- 아직 싱글 제네레이션이지만 제네레이션을 도입했을 때 제네레이션의 사이즈도 동적으로 자동 조절되도록 할 예정
-Xmn옵션을 사용하지 않음
- Young 객체를 Old 객체로 승격시키는 threshold 설정도 자동으로 설정 됨
-XX:TenuringThreashold옵션을 사용하지 않는다.
- 다양한 튜닝 옵션은 Configuration & Tuning 참조
4.1 Setting the Heap Size
- 레퍼런스
- ZGC 튜닝에서 가장 중요한 옵션이 바로 힙의 최대 크기를 지정하는 것이다.
-Xmx옵션으로 최대 힙의 크기를 설정한다.- 일반적으로 메모리 힙 사이즈가 크면 클수록 좋다.
- 메모리 낭비는 바람직하지 않기 때문에 메모리 사용량과 GC의 빈도 사이의 균형을 유지해줄 메모리 힙 사이즈를 찾아야한다.
GC usually requires a developer to specify the heap space size. The specific value will be greater than the total size of the live objects in the heap. The higher proportion of redundant space, the better the GC performance is. For example, if the total size of estimated objects reaches 32GB, the heap space size is set as Xmx40g, which means 40GB of the heap is enabled.
ZGC differs from traditional GC. While ZGC collects objects, Java threads are also allocating new objects. Therefore, ZGC requires a higher proportion of redundant space than traditional GCs.
The total size of objects allocated during each round of ZGC can be estimated by allocation speed and single round ZGC time, so the size of heap space should be greater than the total size of live objects + the total size of objects allocated during a single ZGC.
You can find the preceding allocation speed and single round ZGC time in GC logs.
