ZGC new release

akanana·2021년 10월 6일
0

JavaPerformance

목록 보기
9/9
post-thumbnail

🏐JDK 14


🏀parallel heap pre-touching


ZGC 는 -Xms, -XX:InitialHeapSize 의 상위인 -XX+AlwaysPreTouch 를 이용하여 초기 Heap 을 Touch 후 사용하게 된다. 이를 통해 별도의 overhead 없이 메모리 사용이 가능하다.
이때 이 과정이 Serial 하게 이루어졌고, 큰 Heap Size 에서 긴 시간이 소요된다.
JDK 14 에선 이 과정을 Parallel 하게 진행하기 시작했으며, 이를 통하여 시작 시간을 줄일 수 있게 되었다.

🏀small heap


ZGC 는 큰 heap size 를 다룰때에 다른 GC 들 보다 매우 우월한 성능을 지녔다. 하지만, 작은 heap(특히 128M 이하의 환경에서) 일때에 ZGC 가 오히려 좋지못한 성능을 보이는 경우가 많았다.
가장 큰 이유는, ZGC 는 예비 힙 영역이 필요한데, 이를 할당하고 나서 OutOfMemoryError 가 발생하는 경우가 자주 있었다.

예비 힙(reserve heap)?

ZGC 에서 Relocaiton 작업시에 evacuation 해야 할 영역이 필요하다. 이를 위한 여분의 공간.
기본적으로
(예비 힙) = (작업 스레드) * 2M + 32M

이러한 예비 힙의 크기는 작은 메모리에 부담이 될 수 있다.
이를 위해 middle zpage 를 동적으로 조정, 힙의 3% 이상을 차지하지 않도록 하며, 아주 작은 heap 에서는 middle zpage 를 비활성화 하여 large zpage 로 할당한다.

Large ZPage

Large Zpage 는 N*2M 의 동적인 크기를 가지고 있다.
하지만 절대 Relocation 되지 않는다는 특징을 가지고 있다.

이를 통하여 최소 예비 힙은 최소5%(최소 2M) 로 설정된다.

🏀TTSP 개선


JVM 은 특정 작업을 실행시에 safepoint 라는 STW 를 가진다.

하지만 그림과 같이, 특정 스레드가 민감한 작업을 마치기 위해, 다른 스레드가 강제로 STW 를 가져야 하는 시간이 존재한다.
이를 TTSP(Time-To-Safepoint) 라고 한다. 이는 대규모 Array 를 할당할때에 매우 길어지며(최대 16G) 까지 커질 수 있음.
이를 최적화 하기위해 safepoint-aware 라는 기술을 이용, 아무리 큰 Array 가 할당되어도 문제가 없다.

🏐JDK 15


JDK 15 에서 드디어 ZGC 가 정식적인 제품으로 인정되었다.

🏀Concurrency Allocation


ZGC 는 단 하나의 스레드만이 한 번에 힙을 확장하거나 축소하는 것이 가능하다. 이러한 Global 한 Lock 은 항상 논쟁거리였다.
JDK 15 이후에는 Global Lock 기능을 하지 않도록 조정하였고, 동시 할당량이 크게 증가되었다.

🏀NVRAM


NVRAM 의 발전에 따라, JAVA 는 Heap 을 RAM 이 아닌 NVRAM 에 배치하기 시작하였다.
JDK 10 이후 -XX:AllocateHeapAt 옵션을 통하여 NVRAM 에 할당이 가능했으나, ZGC 만 이가 불가능하였다.
JDK 15버전이후 ZGC 또한 이를 통하여 NVRAM 에 지원이 가능해졌다.

🏀Compressed Class Pointer


Compressed Class Pointer 기능은 Compressed Oops 와 dependency 한 관계였다.
header 구조가 다른 ZGC 는 Compressed Oops 를 사용할 수 없었고, 자연스럽게 Compress Class Pointer 또한 사용할 수 없었다,
JDK 15 에 오면서 두 기능의 depenedency 가 풀렸으며, ZGC 또한 Compressed Class Pointer 를 사용할 수 있게 되었다.

🏀CDS(Class Data Sharing)


CDS 기능또한 Compressed Oops 가 true 인 상황에서만 사용이 가능했었다.
이 또한 JDK 15 로 오면서, dependency 가 풀렸으며, ZGC 또한 CDS 를 사용할 수 있게 되었다.

🏀NUMA


NUMA 를 통해 더 적은 Memory Latencies 로 프로그램 기동이 가능했다.
하지만 ZGC 에서는 Larg zpage 에만 이를 적용하였다.
JDK 15 에 오며, 이는 zpage 의 크기에 상관없이 NUMA 를 통한 인식이 가능해졌다.

🏐JDK 16


🏀10ms -> 1ms


초기 ZGC 의 목표는 어떠한 경우에도 STW 를 10ms 밑으로 줄이겠다는 것이였다. 이 목표를 달성한 ZGC 는 이제 STW 를 1ms 이하로 줄이겠다는 목표를 지니게 되었다.
앞전, ZGC 는 heap size 가 아닌 root set 의 크기에 따라 초기 STW 시간이 증가하였다. 이 말은, 즉 Thread Stack 을 스캔하였고, Thread 수가 더 많을 수록, STW 의 시간이 더 길어진다.
이를 줄이기 위해 JDK 16 부터는 Stack Watermakr 를 이용한다

Stack Watermark?

!!! 내용 추가 필요

🏀In-place Relocation


ZGC 에서 Relocation 과정시, Reserve Region 이라는 별도의 메모리 공간이 필요하다. 이를 통해 ZGC 는 매우 빠른 성능으로 STW 없는 GC가 이루어졌다.
하지만 적은 Heap 환경에서 Reserve Heap 은 문제가 되기도 하며, 이를 통해 OOME 가 발생하기도 한다.
이를 막기위해 JDK 16 에서는 In-Place Relocation 을 지원하기 시작했다.


위 그림과 같이 relocation 작업을 reserve heap 이 아닌 기존의 region 으로 relocation 을 진행하였다.
실제

와 같이 small region 에서 in-place relocation 이 발생하였음을 볼 수 있다.
++ 물론 이와 같은 작업은 더 많은 overhead 를 발생 할 수 있다.

🏐JDK 17


🏀Dynamic Number of GC Threads


ZGC 는 -XX:+UseDynamicNumberOfGCThreads 에 의한 동적 스레드 할당을 무시해왔다.
하지만 JDK 17 부터는 ZGC 또한 위 옵션을 통해 동적으로 스레드를 할당 받을 수 있게 되었다.

🏀Fast JVM Terminate


ctrl+cSystem.exit() 과 같은 동작으로 인해 java process 를 종료시킬때, zgc 가 즉각적인 속도로 종료가 되는 것은 아니다.
특히 zgc는 thread 가 safe 한 상태로 변경되지 않는다면 종료를 시키지 않는데, JDK 17 부터는 GC 사이클을 중단->안전 상태에 신속히 도달하도록 변경 가능.

출처

ZGC 개발자 Per Liden 의 블로그

0개의 댓글