What's the Difference of Proceeding Non-strong References Between ZGC and G1
Dear ZGC experts, Recently we compared ZGC and G1 on JDK 11 for our application and found one big difference for reference proceeding between the two difference GC types. We captured the JFR (Java Flight Recorder) during the AB test, and observed from JDK reference statistics that using ZGC would proceed much more Non-strong references than G1 during each GC phase. (Thousands of weak references and hundreds of soft references were proceeded in ZGC but only a few in G1). Any difference between ZGC and G1 to handle those non-strong references? Another question is that from GC log, the heap size after GC using ZGC was much higher than G1 which was not reasonable to me, as far as I know, ZGC does not have old (survivor) space so it should collect more garbage and the heap size after GC should be lower than G1 GC. Any explanation why we observed the opposite GC logs like below. (The GC logs captured under the exactly same workload for each application instance). ZGC: GC(1721) Garbage Collection (Allocation Rate) 2066M(42%)->834M(17%) G1: GC(864) Pause Young (Normal) (G1 Evacuation Pause) 3286M->342M(4916M) JVM parameters: ZGC, -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZAllocationSpikeTolerance=5 (We set this parameter for more aggressive GC operations to reserve memory for upcoming peak workload in production, not sure if it's recommended) G1, -XX:+UseG1GC -XX:MaxGCPauseMillis=100 Thank you for the help! Best Regards! Jack
Hi, On 7/9/21 6:11 AM, Jack Ling wrote:
Dear ZGC experts,
Recently we compared ZGC and G1 on JDK 11 for our application and found one big difference for reference proceeding between the two difference GC types.
We captured the JFR (Java Flight Recorder) during the AB test, and observed from JDK reference statistics that using ZGC would proceed much more Non-strong references than G1 during each GC phase. (Thousands of weak references and hundreds of soft references were proceeded in ZGC but only a few in G1). Any difference between ZGC and G1 to handle those non-strong references?
I suspect that's just an effect of G1 being generational and ZGC is not. In other words, when G1 is collecting it's young generation it only finds a few of the References since most of them live in the old generation.
Another question is that from GC log, the heap size after GC using ZGC was much higher than G1 which was not reasonable to me, as far as I know, ZGC does not have old (survivor) space so it should collect more garbage and the heap size after GC should be lower than G1 GC. Any explanation why we observed the opposite GC logs like below. (The GC logs captured under the exactly same workload for each application instance).
ZGC: GC(1721) Garbage Collection (Allocation Rate) 2066M(42%)->834M(17%)
G1: GC(864) Pause Young (Normal) (G1 Evacuation Pause) 3286M->342M(4916M)
One difference between ZGC and G1 is that with ZGC the application continues to run and can allocate new objects while the GC is running. I suspect that's what you are seeing here. If you enable more detailed logging (-Xlog:gc*) you will see this in more details. For example: [6.583s][info ][gc,heap ] GC(2) Mark Start Mark End Relocate Start Relocate End High Low [6.583s][info ][gc,heap ] GC(2) Capacity: 2014M (39%) 2014M (39%) 2014M (39%) 2014M (39%) 2014M (39%) 2014M (39%) [6.583s][info ][gc,heap ] GC(2) Free: 3826M (75%) 3310M (65%) 3172M (62%) 3218M (63%) 3826M (75%) 3124M (61%) [6.583s][info ][gc,heap ] GC(2) Used: 1294M (25%) 1810M (35%) 1948M (38%) 1902M (37%) 1996M (39%) 1294M (25%) [6.583s][info ][gc,heap ] GC(2) Live: - 960M (19%) 960M (19%) 960M (19%) - - [6.583s][info ][gc,heap ] GC(2) Allocated: - 516M (10%) 654M (13%) 771M (15%) - - [6.583s][info ][gc,heap ] GC(2) Garbage: - 333M (7%) 333M (7%) 169M (3%) - - [6.583s][info ][gc,heap ] GC(2) Reclaimed: - - 0M (0%) 163M (3%) - - See the "Allocated:" line. This shows you how much memory the application has allocated since the GC started. In this example, it allocated an additional 771M while it GC was running. Anything allocated while the GC cycle is in progress will be considered live and will be eligible for garbage collection in the next cycle. /Per
JVM parameters:
ZGC, -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZAllocationSpikeTolerance=5 (We set this parameter for more aggressive GC operations to reserve memory for upcoming peak workload in production, not sure if it's recommended)
G1, -XX:+UseG1GC -XX:MaxGCPauseMillis=100
Thank you for the help!
Best Regards! Jack
participants (2)
-
Jack Ling
-
Per Liden