Z Garbage Collector in Java
Today, it’s common for applications to respond to thousands or even millions of users concurrently. Such applications need immeasurable amounts of memory. However, managing all that memory may easily impact application performance. To overcome this issue java 11 includes a lot of improvements and changes in the GC(Garbage Collection) domain. Java 11 has some great features, one is Z Garbage Collector (ZGC). The Z Garbage Collector, also known as ZGC, is a low latency scalable garbage collector designed to meet the following objectives.
- Pause times shall not exceed 10 ms
- Handle heaps ranging from an 8MB to 16TB in size
- Pause times do not increase with the size of the heap or live-set.
In brief, Z garbage Collector possesses characteristics as follows:
- NUMA-aware: Non-uniform memory access (NUMA) is a way of configuring a cluster of microprocessors into a multiprocessing system, so that memory can be shared locally and performance can be improved and the system’s ability extended.
- Using colored pointers
- Using load barriers
(A) Features of Z Garbage Collector
- ZGC performs all costly work concurrently, without stopping application thread execution for more than 10ms which makes it ideal for applications needing low latency and/or using a very large heap (multi-terabytes).
- ZGC is more flexible in configuring its size and scheme.
- ZGC is a single-generation GC. It also supports partial compaction.
(B) Understanding Z Garbage Collector
To work with Z Garbage Collector we have to follow multiple steps. You have to install the JDK binary, which is specific to Linux/x64, and build and start it. You can use the following commands to download ZGC and build it on your system:
$ hg clone http://hg.openjdk.java.net/jdk/jdk $ cd zgc $ sh configure --with-jvm-features=zgc $ make images
After execution of the given commands, you can find the JDK root directory in the following location:
(C) Implementation: Basic HelloGFG class
Hello to new Garbage Collector - ZGC!
Now, The following command can be used to enable ZGC and use it:java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC HelloGFG
For enabling basic GC logging, the user can add the -Xlog:gc option. Detailed logging is helpful while fine-tuning an application. The user can enable it by using the -Xlog:gc* option as follows:
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc* HelloGFG
The previous command will output all the logs to the console, which could make it difficult to search for specific content. The user can specify the logs to be written to a file as follows:
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc:mylog.log* HelloGFG
(D) Z Garbage Collector heap
ZGC divides memory into regions, also called ZPages. These can be dynamically created and destroyed. ZGC heap can have multiple occurrences of these heap regions. The medium and large regions are allocated contiguously. These can also be dynamically sized (unlike the G1 GC), which are multiples of 2 MB. Here are the size groups of heap regions:
|Large||N × 2 MB|
(E) Z Garbage Collector phases:
The GC cycle of ZGC is divided into three pauses.
- Pause Mark Start: In the first phase, ZGC walks through the object graph to mark the object’s live or garbage. This phase also includes the remapping of live data. This is by far one of the most heavy-duty workloads in the ZGC GC cycle.
- Pause Mark End: The second phase is where reference preprocessing is done. The class unloading and relocation set selection are also done in this phase. It also includes the relocation set selection. ZGC marks the regions it wants to compact.
- Pause Relocate Start: The last phase is where the heavy job of compacting the heap happens.
(F) Colored pointers
Colored pointers are one of the core concepts of ZGC. It enables ZGC to find, mark, locate, and remap the objects. It doesn’t support x32 platforms. Implementation of colored points needs virtual address masking, which could be accomplished either in the hardware, operating system, or software. The following diagram shows the 64-bit pointer layout:
The first 18 bits are reserved for future use. The 42 bits can address up to 4 TB of address space. Now comes the remaining, intriguing, 4 bits. The Marked1 and Marked0 bits are used to mark objects for garbage collection. By setting the single bit for Remapped, an object can be marked not pointing to into the relocation set. The last 1-bit for finalizing relates to concurrent reference processing. It marks that an object can only be reachable through a finalizer.
As shown in the preceding diagram, the 64-bit object reference is divided as follows:
|18 bits||Unused bits|
|42 bits||Object Address|
(G) Tuning Z Garbage Collector
ZGC is a concurrent garbage collector. By setting the amount of CPU time that should be assigned to ZGC threads, the user can control how often the GC kicks in. It can be done so by using the following option:
A higher value for the ConcGCThreads option will leave less amount of CPU time for your application. On the other hand, a lower value may result in your application struggling for memory; your application might generate more garbage than what is collected by ZGC. ZGC can also use default values for ConcGCThreads. To fine-tune your application on this parameter, you might prefer to execute against test values.
For advanced ZGC tuning, the user can also enable large pages for enhanced performance of your application. It can be done by using the following option:
Instead of enabling large pages, the user can also enable transparent huge pages by using the following option:
The preceding option also includes additional settings and configurations, which can be accessed by using ZGC’s official wiki page.
ZGC is a NUMA-aware GC. Applications executing on the NUMA machine can result in a noticeable performance gain. By default, NUMA support is enabled for ZGC. However, if the JVM realizes that it is bound to a subset in the JVM, this feature can be disabled. To override a JVM’s decision, the following option can be used:
In this article, we saw that ZGC intends to support large heap sizes with low application pause times. We have briefly discussed the scalable, low latency GC for OpenJDK—ZGC. It is an experimental GC, which has been written from scratch. As a concurrent GC, it promises max latency to be less than 10 milliseconds, which doesn’t increase with heap size or live data. At present, it only works with Linux/x64. More platforms can be supported in the future if there is considerable demand for them.