From d4e6434453e0cf4811020da239bdef6cf332621b Mon Sep 17 00:00:00 2001 From: Anthony Kiselev Date: Wed, 11 Jun 2025 10:17:31 -0500 Subject: [PATCH 1/5] Report ZGC individual collections instead of cycles Previously, the ZGC parser would attempt to construct a single event for each minor/major cycle, with each minor cycle containing a single young collection, and each major cycle containing a single young and a single old collection. This created a few problems. First, the implementation of the parser assumed that only one cycle could be active at any given time. As a result, any time a minor cycle started before the previous major cycle was finished, all data collected about the major cycle would be lost. Second, the data model for a MajorZGCCycle assumed there could be only one young collection per cycle. This is not the case. There can be (and frequently are) multiple young collections in a major cycle. Even if the implementation and datamodel were fixed to account for the concurrent nature of generational ZGC, grouping collections by cycle would still create API usability problems. Individual collections within a cycle independently report various JVM/heap level metrics at specific points in time. Within a single major cycle, those points in time may be very far apart, and overlap with a large number of minor cycles. If an end user wished to construct a timeline for a particular metric (for example, heap occupancy), they would need to traverse all the reported cycles, extract the metrics from the individual collections, and put them in order. To address the above issues, the parser and data models are refactored to report each individual collection (young, old, or full) immediately once they are completed instead of waiting until the parent cycle is done. The parser maintains 3 independent forward references (one for each collection type: old, young, and full). As a result, the parser will not lose state even when lines from an old collection are intermixed with lines from a young collection. --- .../CollectionCycleCountsAggregator.java | 18 +- ...eapOccupancyAfterCollectionAggregator.java | 20 +- .../event/GarbageCollectionTypes.java | 5 +- .../gctoolkit/event/zgc/FullZGCCycle.java | 336 ----------------- .../gctoolkit/event/zgc/MajorZGCCycle.java | 64 ---- .../gctoolkit/event/zgc/MinorZGCCycle.java | 55 --- .../zgc/{ZGCCycle.java => ZGCCollection.java} | 33 +- .../event/zgc/ZGCCollectionType.java | 12 + .../event/zgc/ZGCFullCollection.java | 23 ++ .../gctoolkit/event/zgc/ZGCOldCollection.java | 23 ++ .../event/zgc/ZGCYoungCollection.java | 23 ++ .../com/microsoft/gctoolkit/jvm/Diary.java | 6 + .../gctoolkit/jvm/SupportedFlags.java | 4 +- .../microsoft/gctoolkit/parser/ZGCParser.java | 355 +++++++----------- .../gctoolkit/parser/jvm/UnifiedDiarizer.java | 19 +- .../gctoolkit/parser/unified/ZGCPatterns.java | 16 +- .../parser/GenerationalZGCParserTest.java | 281 ++++++++++++-- .../gctoolkit/parser/ZGCParserRulesTest.java | 17 +- .../gctoolkit/parser/ZGCParserTest.java | 11 +- .../CollectionCycleCountsAggregator.java | 18 +- .../HeapOccupancyAfterCollection.java | 18 +- 21 files changed, 573 insertions(+), 784 deletions(-) delete mode 100644 api/src/main/java/com/microsoft/gctoolkit/event/zgc/FullZGCCycle.java delete mode 100644 api/src/main/java/com/microsoft/gctoolkit/event/zgc/MajorZGCCycle.java delete mode 100644 api/src/main/java/com/microsoft/gctoolkit/event/zgc/MinorZGCCycle.java rename api/src/main/java/com/microsoft/gctoolkit/event/zgc/{ZGCCycle.java => ZGCCollection.java} (94%) create mode 100644 api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCFullCollection.java create mode 100644 api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCOldCollection.java create mode 100644 api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCYoungCollection.java diff --git a/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/CollectionCycleCountsAggregator.java b/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/CollectionCycleCountsAggregator.java index ea791bc1..dc34f9db 100644 --- a/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/CollectionCycleCountsAggregator.java +++ b/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/CollectionCycleCountsAggregator.java @@ -7,9 +7,9 @@ import com.microsoft.gctoolkit.event.g1gc.G1GCPauseEvent; import com.microsoft.gctoolkit.event.generational.GenerationalGCPauseEvent; import com.microsoft.gctoolkit.event.shenandoah.ShenandoahCycle; -import com.microsoft.gctoolkit.event.zgc.FullZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MajorZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MinorZGCCycle; +import com.microsoft.gctoolkit.event.zgc.ZGCFullCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCYoungCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCOldCollection; @Aggregates({EventSource.G1GC,EventSource.GENERATIONAL,EventSource.ZGC,EventSource.SHENANDOAH}) public class CollectionCycleCountsAggregator extends Aggregator { @@ -19,21 +19,21 @@ public CollectionCycleCountsAggregator(CollectionCycleCountsAggregation results) register(GenerationalGCPauseEvent.class, this::count); register(G1GCPauseEvent.class, this::count); register(G1GCConcurrentEvent.class, this::count); - register(FullZGCCycle.class,this::count); - register(MajorZGCCycle.class,this::count); - register(MinorZGCCycle.class,this::count); + register(ZGCFullCollection.class, this::count); + register(ZGCOldCollection.class, this::count); + register(ZGCYoungCollection.class, this::count); register(ShenandoahCycle.class,this::count); } - private void count(FullZGCCycle event) { + private void count(ZGCFullCollection event) { aggregation().count(event.getGarbageCollectionType()); } - private void count(MajorZGCCycle event) { + private void count(ZGCOldCollection event) { aggregation().count(event.getGarbageCollectionType()); } - private void count(MinorZGCCycle event) { + private void count(ZGCYoungCollection event) { aggregation().count(event.getGarbageCollectionType()); } diff --git a/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/HeapOccupancyAfterCollectionAggregator.java b/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/HeapOccupancyAfterCollectionAggregator.java index d36e7a54..1fede8f0 100644 --- a/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/HeapOccupancyAfterCollectionAggregator.java +++ b/IT/src/main/java/com/microsoft/gctoolkit/integration/aggregation/HeapOccupancyAfterCollectionAggregator.java @@ -6,9 +6,9 @@ import com.microsoft.gctoolkit.event.g1gc.G1GCPauseEvent; import com.microsoft.gctoolkit.event.generational.GenerationalGCPauseEvent; import com.microsoft.gctoolkit.event.shenandoah.ShenandoahCycle; -import com.microsoft.gctoolkit.event.zgc.FullZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MajorZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MinorZGCCycle; +import com.microsoft.gctoolkit.event.zgc.ZGCFullCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCOldCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCYoungCollection; @Aggregates({EventSource.G1GC,EventSource.GENERATIONAL,EventSource.ZGC,EventSource.SHENANDOAH}) public class HeapOccupancyAfterCollectionAggregator extends Aggregator { @@ -17,17 +17,17 @@ public HeapOccupancyAfterCollectionAggregator(HeapOccupancyAfterCollectionAggreg super(results); register(GenerationalGCPauseEvent.class, this::extractHeapOccupancy); register(G1GCPauseEvent.class, this::extractHeapOccupancy); - register(FullZGCCycle.class,this::extractHeapOccupancy); - register(MajorZGCCycle.class,this::extractHeapOccupancy); - register(MinorZGCCycle.class,this::extractHeapOccupancy); + register(ZGCFullCollection.class, this::extractHeapOccupancy); + register(ZGCOldCollection.class, this::extractHeapOccupancy); + register(ZGCYoungCollection.class, this::extractHeapOccupancy); register(ShenandoahCycle.class,this::extractHeapOccupancy); } - private void extractHeapOccupancy(MinorZGCCycle event) { - aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getYoungCycle().getMemorySummary().getOccupancyAfter()); + private void extractHeapOccupancy(ZGCYoungCollection event) { + aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getMemorySummary().getOccupancyAfter()); } - private void extractHeapOccupancy(MajorZGCCycle event) { + private void extractHeapOccupancy(ZGCOldCollection event) { aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getMemorySummary().getOccupancyAfter()); } @@ -41,7 +41,7 @@ private void extractHeapOccupancy(G1GCPauseEvent event) { aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getHeap().getOccupancyAfterCollection()); } - private void extractHeapOccupancy(FullZGCCycle event) { + private void extractHeapOccupancy(ZGCFullCollection event) { aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getMemorySummary().getOccupancyAfter()); } diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java b/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java index fc6f6a31..e6af2e1a 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java +++ b/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java @@ -56,8 +56,9 @@ public enum GarbageCollectionTypes implements LabelledGCEventType { G1Trap("G1GC Trap"), Unknown("Unknown"), ZGCFull("ZGC FULL"), - ZGCMajor("ZGC Major"), - ZGCMinor("ZGC Minor"), + ZGCMajorOld("ZGC Major Old"), + ZGCMajorYoung("ZGC Major Old"), + ZGCMinorYoung("ZGC Minor Young"), Shenandoah("Shenandoah"); private final String label; diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/FullZGCCycle.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/FullZGCCycle.java deleted file mode 100644 index a3dc0345..00000000 --- a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/FullZGCCycle.java +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -package com.microsoft.gctoolkit.event.zgc; - -import com.microsoft.gctoolkit.event.GCCause; -import com.microsoft.gctoolkit.event.GCEvent; -import com.microsoft.gctoolkit.event.GarbageCollectionTypes; -import com.microsoft.gctoolkit.time.DateTimeStamp; - -import java.util.List; - -public class FullZGCCycle extends GCEvent { - private ZGCCycle delegate; - - public FullZGCCycle(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, GCCause cause, double duration, ZGCCycle delegate) { - super(timeStamp, gcType, cause, duration); - this.delegate = delegate; - } - - public void setZGCCycle(ZGCCycle zgcCycle) { - this.delegate = zgcCycle; - } - - public ZGCReferenceSummary getSoftRefSummary() { - return delegate.getSoftRefSummary(); - } - - public ZGCReferenceSummary getFinalRefSummary() { - return delegate.getFinalRefSummary(); - } - - public ZGCMemoryPoolSummary getMarkEnd() { - return delegate.getMarkEnd(); - } - - public DateTimeStamp getConcurrentRemapRootsStart() { - return delegate.getConcurrentRemapRootsStart(); - } - - public DateTimeStamp getRemapRememberedStart() { - return delegate.getRemapRememberedStart(); - } - - public ZGCPromotedSummary getPromotedSummary() { - return delegate.getPromotedSummary(); - } - - public ZGCMetaspaceSummary getMetaspaceSummary() { - return delegate.getMetaspaceSummary(); - } - - public ZGCReferenceSummary getWeakRefSummary() { - return delegate.getWeakRefSummary(); - } - - public DateTimeStamp getConcurrentSelectRelocationSetTimeStamp() { - return delegate.getConcurrentSelectRelocationSetTimeStamp(); - } - - public DateTimeStamp getRemapRootColoredStart() { - return delegate.getRemapRootColoredStart(); - } - - public ZGCPhase getPhase() { - return delegate.getPhase(); - } - - public double getRemapRootsColoredDuration() { - return delegate.getRemapRootsColoredDuration(); - } - - public double getConcurrentMarkContinueDuration() { - return delegate.getConcurrentMarkContinueDuration(); - } - - public double getConcurrentRemapRootsDuration() { - return delegate.getConcurrentRemapRootsDuration(); - } - - public double getPauseMarkRelocateDuration() { - return delegate.getPauseMarkRelocateDuration(); - } - - public ZGCAllocatedSummary getAllocatedSummary() { - return delegate.getAllocatedSummary(); - } - - public ZGCReferenceSummary getPhantomRefSummary() { - return delegate.getPhantomRefSummary(); - } - - public ZGCMarkSummary getMarkSummary() { - return delegate.getMarkSummary(); - } - - public double getRemapRememberedDuration() { - return delegate.getRemapRememberedDuration(); - } - - public ZGCGarbageSummary getGarbageSummary() { - return delegate.getGarbageSummary(); - } - - public DateTimeStamp getConcurrentResetRelocationSetTimeStamp() { - return delegate.getConcurrentResetRelocationSetTimeStamp(); - } - - public double getConcurrentMarkFreeDuration() { - return delegate.getConcurrentMarkFreeDuration(); - } - - public ZGCMemoryPoolSummary getMarkStart() { - return delegate.getMarkStart(); - } - - public ZGCLiveSummary getLiveSummary() { - return delegate.getLiveSummary(); - } - - public DateTimeStamp getConcurrentProcessNonStrongReferencesTimeStamp() { - return delegate.getConcurrentProcessNonStrongReferencesTimeStamp(); - } - - public DateTimeStamp getConcurrentMarkContinueTimeStamp() { - return delegate.getConcurrentMarkContinueTimeStamp(); - } - - public ZGCCollectionType getType() { - return delegate.getType(); - } - - public ZGCMemoryPoolSummary getRelocateStart() { - return delegate.getRelocateStart(); - } - - public DateTimeStamp getMarkFollowStart() { - return delegate.getMarkFollowStart(); - } - - public double getPauseMarkEndDuration() { - return delegate.getPauseMarkEndDuration(); - } - - public double getConcurrentSelectRelocationSetDuration() { - return delegate.getConcurrentSelectRelocationSetDuration(); - } - - public double getMarkRootsDuration() { - return delegate.getMarkRootsDuration(); - } - - public double[] getMmu() { - return delegate.getMmu(); - } - - public double getConcurrentProcessNonStrongReferencesDuration() { - return delegate.getConcurrentProcessNonStrongReferencesDuration(); - } - - public DateTimeStamp getConcurrentRelocateTimeStamp() { - return delegate.getConcurrentRelocateTimeStamp(); - } - - public DateTimeStamp getPauseMarkStartTimeStamp() { - return delegate.getPauseMarkStartTimeStamp(); - } - - public double getPauseMarkStartDuration() { - return delegate.getPauseMarkStartDuration(); - } - - public OccupancySummary getUsedOccupancySummary() { - return delegate.getUsedOccupancySummary(); - } - - public DateTimeStamp getConcurrentMarkTimeStamp() { - return delegate.getConcurrentMarkTimeStamp(); - } - - public double getMMU(int percentage) { - return delegate.getMMU(percentage); - } - - public ZGCMemorySummary getMemorySummary() { - return delegate.getMemorySummary(); - } - - public ZGCCompactedSummary getCompactedSummary() { - return delegate.getCompactedSummary(); - } - - public long getGcId() { - return delegate.getGcId(); - } - - public double getConcurrentResetRelocationSetDuration() { - return delegate.getConcurrentResetRelocationSetDuration(); - } - - public DateTimeStamp getConcurrentMarkFreeTimeStamp() { - return delegate.getConcurrentMarkFreeTimeStamp(); - } - - public DateTimeStamp getPauseMarkEndTimeStamp() { - return delegate.getPauseMarkEndTimeStamp(); - } - - public double getConcurrentRelocateDuration() { - return delegate.getConcurrentRelocateDuration(); - } - - public double getLoadAverageAt(int time) { - return delegate.getLoadAverageAt(time); - } - - public DateTimeStamp getPauseRelocateStartTimeStamp() { - return delegate.getPauseRelocateStartTimeStamp(); - } - - public double[] getLoad() { - return delegate.getLoad(); - } - - public double getPauseRelocateStartDuration() { - return delegate.getPauseRelocateStartDuration(); - } - - public DateTimeStamp getRemapRootsUncoloredStart() { - return delegate.getRemapRootsUncoloredStart(); - } - - public DateTimeStamp getMarkRootsStart() { - return delegate.getMarkRootsStart(); - } - - public double getRemapRootsUncoloredDuration() { - return delegate.getRemapRootsUncoloredDuration(); - } - - public double getConcurrentMarkDuration() { - return delegate.getConcurrentMarkDuration(); - } - - public ZGCReclaimSummary getReclaimSummary() { - return delegate.getReclaimSummary(); - } - - public double getMarkFollowDuration() { - return delegate.getMarkFollowDuration(); - } - - public ZGCMemoryPoolSummary getRelocateEnd() { - return delegate.getRelocateEnd(); - } - - public ZGCHeapCapacitySummary getHeapCapacitySummary() { - return delegate.getHeapCapacitySummary(); - } - - public ZGCNMethodSummary getNMethodSummary() { - return delegate.getNMethodSummary(); - } - - public ZGCPageSummary getSmallPageSummary() { - return delegate.getSmallPageSummary(); - } - - public ZGCPageSummary getMediumPageSummary() { - return delegate.getMediumPageSummary(); - } - - public ZGCPageSummary getLargePageSummary() { - return delegate.getLargePageSummary(); - } - - public long getForwardingUsage() { - return delegate.getForwardingUsage(); - } - - public List getAgeTableSummary() { - return delegate.getAgeTableSummary(); - } -} - -// Concurrent Mark duration -// Pause mark end duration -// Concurrent reference processing duration -// Concurrent reset relocation set duration -// Concurrent select relocation set duration -// Pause relocate start -// Load -// MMU -// Concurrent relocate -// Relocation volume -// NMethods, registered, unregistered -// Metaspace used, capacity committed, reserved -// Soft, weak, final, phantom.. encountered, discovered, enqueued -// Memory stats - -/* -[32.121s][info][gc,start ] GC(2) Garbage Collection (Metadata GC Threshold) -[32.121s][info][gc,phases ] GC(2) Pause Mark Start 0.023ms -[32.166s][info][gc,phases ] GC(2) Concurrent Mark 44.623ms -[32.166s][info][gc,phases ] GC(2) Pause Mark End 0.029ms -[32.166s][info][gc,phases ] GC(2) Concurrent Mark Free 0.001ms -[32.172s][info][gc,phases ] GC(2) Concurrent Process Non-Strong References 5.797ms -[32.172s][info][gc,phases ] GC(2) Concurrent Reset Relocation Set 0.012ms -[32.178s][info][gc,phases ] GC(2) Concurrent Select Relocation Set 6.446ms -[32.179s][info][gc,phases ] GC(2) Pause Relocate Start 0.024ms -[32.193s][info][gc,phases ] GC(2) Concurrent Relocate 14.013ms -[32.193s][info][gc,load ] GC(2) Load: 7.28/6.63/5.01 -[32.193s][info][gc,mmu ] GC(2) MMU: 2ms/98.2%, 5ms/99.3%, 10ms/99.5%, 20ms/99.7%, 50ms/99.9%, 100ms/99.9% -[32.193s][info][gc,marking ] GC(2) Mark: 4 stripe(s), 3 proactive flush(es), 1 terminate flush(es), 0 completion(s), 0 continuation(s) -[32.193s][info][gc,marking ] GC(2) Mark Stack Usage: 32M -[32.193s][info][gc,metaspace] GC(2) Metaspace: 60M used, 60M committed, 1080M reserved -[32.193s][info][gc,ref ] GC(2) Soft: 5447 encountered, 0 discovered, 0 enqueued -[32.193s][info][gc,ref ] GC(2) Weak: 5347 encountered, 2016 discovered, 810 enqueued -[32.193s][info][gc,ref ] GC(2) Final: 1041 encountered, 113 discovered, 105 enqueued -[32.193s][info][gc,ref ] GC(2) Phantom: 558 encountered, 501 discovered, 364 enqueued -[32.193s][info][gc,reloc ] GC(2) Small Pages: 235 / 470M, Empty: 32M, Relocated: 40M, In-Place: 0 -[32.193s][info][gc,reloc ] GC(2) Medium Pages: 2 / 64M, Empty: 0M, Relocated: 3M, In-Place: 0 -[32.193s][info][gc,reloc ] GC(2) Large Pages: 3 / 24M, Empty: 8M, Relocated: 0M, In-Place: 0 -[32.193s][info][gc,reloc ] GC(2) Forwarding Usage: 13M -[32.193s][info][gc,heap ] GC(2) Min Capacity: 8M(0%) -[32.193s][info][gc,heap ] GC(2) Max Capacity: 28686M(100%) -[32.193s][info][gc,heap ] GC(2) Soft Max Capacity: 28686M(100%) -[32.193s][info][gc,heap ] GC(2) Mark Start Mark End Relocate Start Relocate End High Low -[32.193s][info][gc,heap ] GC(2) Capacity: 1794M (6%) 1794M (6%) 1794M (6%) 1794M (6%) 1794M (6%) 1794M (6%) -[32.193s][info][gc,heap ] GC(2) Free: 28128M (98%) 28110M (98%) 28148M (98%) 28560M (100%) 28560M (100%) 28108M (98%) -[32.193s][info][gc,heap ] GC(2) Used: 558M (2%) 576M (2%) 538M (2%) 126M (0%) 578M (2%) 126M (0%) -[32.193s][info][gc,heap ] GC(2) Live: - 71M (0%) 71M (0%) 71M (0%) - - -[32.193s][info][gc,heap ] GC(2) Allocated: - 18M (0%) 20M (0%) 18M (0%) - - -[32.193s][info][gc,heap ] GC(2) Garbage: - 486M (2%) 446M (2%) 35M (0%) - - -[32.193s][info][gc,heap ] GC(2) Reclaimed: - - 40M (0%) 450M (2%) - - -[32.193s][info][gc ] GC(2) Garbage Collection (Metadata GC Threshold) 558M(2%)->126M(0%) -*/ diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/MajorZGCCycle.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/MajorZGCCycle.java deleted file mode 100644 index 1852c514..00000000 --- a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/MajorZGCCycle.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -package com.microsoft.gctoolkit.event.zgc; - -import com.microsoft.gctoolkit.event.GCCause; -import com.microsoft.gctoolkit.event.GCEvent; -import com.microsoft.gctoolkit.event.GarbageCollectionTypes; -import com.microsoft.gctoolkit.time.DateTimeStamp; - -public class MajorZGCCycle extends GCEvent { - private ZGCCycle oldCycle; - private ZGCCycle youngCycle; - private ZGCMemorySummary memorySummary; - private long gcId; - - public MajorZGCCycle(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, GCCause cause, double duration) { - super(timeStamp, gcType, cause, duration); - } - - public MajorZGCCycle(DateTimeStamp timeStamp, double duration) { - super(timeStamp, duration); - } - - public MajorZGCCycle(DateTimeStamp timeStamp, GCCause cause, double duration) { - super(timeStamp, cause, duration); - } - - public MajorZGCCycle(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, double duration) { - super(timeStamp, gcType, duration); - } - - public ZGCCycle getOldCycle() { - return oldCycle; - } - - public void setOldCycle(ZGCCycle oldCycle) { - this.oldCycle = oldCycle; - } - - public ZGCCycle getYoungCycle() { - return youngCycle; - } - - public void setYoungCycle(ZGCCycle youngCycle) { - this.youngCycle = youngCycle; - } - - public ZGCMemorySummary getMemorySummary() { - return memorySummary; - } - - public void setMemorySummary(ZGCMemorySummary memorySummary) { - this.memorySummary = memorySummary; - } - - public void setGcId(long gcId) { - - this.gcId = gcId; - } - - public long getGcId() { - return gcId; - } -} diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/MinorZGCCycle.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/MinorZGCCycle.java deleted file mode 100644 index 1b2d20b1..00000000 --- a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/MinorZGCCycle.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -package com.microsoft.gctoolkit.event.zgc; - -import com.microsoft.gctoolkit.event.GCCause; -import com.microsoft.gctoolkit.event.GCEvent; -import com.microsoft.gctoolkit.event.GarbageCollectionTypes; -import com.microsoft.gctoolkit.time.DateTimeStamp; - -public class MinorZGCCycle extends GCEvent { - private ZGCCycle youngCycle; - private ZGCMemorySummary memorySummary; - private long gcId; - - public MinorZGCCycle(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, GCCause cause, double duration) { - super(timeStamp, gcType, cause, duration); - } - - public MinorZGCCycle(DateTimeStamp timeStamp, double duration) { - super(timeStamp, duration); - } - - public MinorZGCCycle(DateTimeStamp timeStamp, GCCause cause, double duration) { - super(timeStamp, cause, duration); - } - - public MinorZGCCycle(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, double duration) { - super(timeStamp, gcType, duration); - } - - public ZGCCycle getYoungCycle() { - return youngCycle; - } - - public void setYoungCycle(ZGCCycle youngCycle) { - this.youngCycle = youngCycle; - } - - public ZGCMemorySummary getMemorySummary() { - return memorySummary; - } - - public void setMemorySummary(ZGCMemorySummary memorySummary) { - this.memorySummary = memorySummary; - } - - public void setGcId(long gcId) { - - this.gcId = gcId; - } - - public long getGcId() { - return gcId; - } -} diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCycle.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollection.java similarity index 94% rename from api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCycle.java rename to api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollection.java index d06173f8..6ec65d8d 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCycle.java +++ b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollection.java @@ -1,10 +1,13 @@ package com.microsoft.gctoolkit.event.zgc; +import com.microsoft.gctoolkit.event.GCCause; +import com.microsoft.gctoolkit.event.GCEvent; +import com.microsoft.gctoolkit.event.GarbageCollectionTypes; import com.microsoft.gctoolkit.time.DateTimeStamp; import java.util.List; -public class ZGCCycle { +public class ZGCCollection extends GCEvent { private DateTimeStamp markRootsStart; private double markRootsDuration; private DateTimeStamp markFollowStart; @@ -20,7 +23,7 @@ public class ZGCCycle { private ZGCCompactedSummary compactedSummary; private ZGCCollectionType type; private ZGCPhase phase; - private OccupancySummary usedOccupancySummary; + private OccupancySummary generationUsedSummary; private long gcId; private DateTimeStamp pauseMarkStartTimeStamp; private double pauseMarkStartDuration; @@ -68,6 +71,24 @@ public class ZGCCycle { private long forwardingUsage; private List ageTableSummary; + public ZGCCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, GCCause cause, double duration) { + super(timeStamp, gcType, cause, duration); + } + + public ZGCCollection(DateTimeStamp timeStamp, double duration) { + super(timeStamp, duration); + } + + public ZGCCollection(DateTimeStamp timeStamp, GCCause cause, double duration) { + super(timeStamp, cause, duration); + } + + public ZGCCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, double duration) { + super(timeStamp, gcType, duration); + } + + + public ZGCReferenceSummary getSoftRefSummary() { return softRefSummary; } @@ -395,13 +416,13 @@ public void setCompactedSummary(ZGCCompactedSummary compactedSummary) { this.compactedSummary = compactedSummary; } - public void setusedOccupancySummary(OccupancySummary usedOccupancySummary) { + public void setGenerationUsedSummary(OccupancySummary usedOccupancySummary) { - this.usedOccupancySummary = usedOccupancySummary; + this.generationUsedSummary = usedOccupancySummary; } - public OccupancySummary getUsedOccupancySummary() { - return usedOccupancySummary; + public OccupancySummary getGenerationUsedSummary() { + return generationUsedSummary; } public ZGCCollectionType getType() { diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollectionType.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollectionType.java index 38838afc..5292d4eb 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollectionType.java +++ b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollectionType.java @@ -20,4 +20,16 @@ public static ZGCCollectionType get(String label) { .findFirst() .orElse(null); } + + public static ZGCCollectionType fromPhase(ZGCPhase phase){ + if(phase == ZGCPhase.FULL){ + return ZGCCollectionType.FULL; + } else if (phase == ZGCPhase.MAJOR_YOUNG || phase == ZGCPhase.MAJOR_OLD){ + return ZGCCollectionType.MAJOR; + } else if (phase == ZGCPhase.MINOR_YOUNG){ + return ZGCCollectionType.MINOR; + } else { + throw new IllegalArgumentException(String.format("Unknown ZGCPhase: %s", phase)); + } + } } diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCFullCollection.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCFullCollection.java new file mode 100644 index 00000000..ff359ffc --- /dev/null +++ b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCFullCollection.java @@ -0,0 +1,23 @@ +package com.microsoft.gctoolkit.event.zgc; + +import com.microsoft.gctoolkit.event.GCCause; +import com.microsoft.gctoolkit.event.GarbageCollectionTypes; +import com.microsoft.gctoolkit.time.DateTimeStamp; + +public class ZGCFullCollection extends ZGCCollection { + public ZGCFullCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, GCCause cause, double duration) { + super(timeStamp, gcType, cause, duration); + } + + public ZGCFullCollection(DateTimeStamp timeStamp, double duration) { + super(timeStamp, duration); + } + + public ZGCFullCollection(DateTimeStamp timeStamp, GCCause cause, double duration) { + super(timeStamp, cause, duration); + } + + public ZGCFullCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, double duration) { + super(timeStamp, gcType, duration); + } +} diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCOldCollection.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCOldCollection.java new file mode 100644 index 00000000..059f1cf1 --- /dev/null +++ b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCOldCollection.java @@ -0,0 +1,23 @@ +package com.microsoft.gctoolkit.event.zgc; + +import com.microsoft.gctoolkit.event.GCCause; +import com.microsoft.gctoolkit.event.GarbageCollectionTypes; +import com.microsoft.gctoolkit.time.DateTimeStamp; + +public class ZGCOldCollection extends ZGCCollection { + public ZGCOldCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, GCCause cause, double duration) { + super(timeStamp, gcType, cause, duration); + } + + public ZGCOldCollection(DateTimeStamp timeStamp, double duration) { + super(timeStamp, duration); + } + + public ZGCOldCollection(DateTimeStamp timeStamp, GCCause cause, double duration) { + super(timeStamp, cause, duration); + } + + public ZGCOldCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, double duration) { + super(timeStamp, gcType, duration); + } +} diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCYoungCollection.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCYoungCollection.java new file mode 100644 index 00000000..d4c77205 --- /dev/null +++ b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCYoungCollection.java @@ -0,0 +1,23 @@ +package com.microsoft.gctoolkit.event.zgc; + +import com.microsoft.gctoolkit.event.GCCause; +import com.microsoft.gctoolkit.event.GarbageCollectionTypes; +import com.microsoft.gctoolkit.time.DateTimeStamp; + +public class ZGCYoungCollection extends ZGCCollection { + public ZGCYoungCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, GCCause cause, double duration) { + super(timeStamp, gcType, cause, duration); + } + + public ZGCYoungCollection(DateTimeStamp timeStamp, double duration) { + super(timeStamp, duration); + } + + public ZGCYoungCollection(DateTimeStamp timeStamp, GCCause cause, double duration) { + super(timeStamp, cause, duration); + } + + public ZGCYoungCollection(DateTimeStamp timeStamp, GarbageCollectionTypes gcType, double duration) { + super(timeStamp, gcType, duration); + } +} diff --git a/api/src/main/java/com/microsoft/gctoolkit/jvm/Diary.java b/api/src/main/java/com/microsoft/gctoolkit/jvm/Diary.java index 5ecdcdbe..d43522d1 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/jvm/Diary.java +++ b/api/src/main/java/com/microsoft/gctoolkit/jvm/Diary.java @@ -50,6 +50,8 @@ TLAB_DATA, // 25 PRINT_PROMOTION_FAILURE, // 26 PRINT_FLS_STATISTICS // 27 + PRINT_CPU_TIMES // 28 + GENERATIONAL_ZGC // 29 */ public class Diary { @@ -174,6 +176,10 @@ public boolean isZGC() { return isTrue(SupportedFlags.ZGC); } + public boolean isGenerationalZGC(){ + return isTrue(SupportedFlags.GENERATIONAL_ZGC); + } + public boolean isShenandoah() { return isTrue(SupportedFlags.SHENANDOAH); } diff --git a/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java b/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java index 2f5d9f8a..0ca78ce5 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java +++ b/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java @@ -37,6 +37,8 @@ public enum SupportedFlags { PRINT_PROMOTION_FAILURE, // 26 PRINT_FLS_STATISTICS, // 27 - PRINT_CPU_TIMES // 28 + PRINT_CPU_TIMES, // 28 + + GENERATIONAL_ZGC, // 29 } diff --git a/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java b/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java index cad0aaf9..dd72d93f 100644 --- a/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java +++ b/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java @@ -10,22 +10,22 @@ import com.microsoft.gctoolkit.event.jvm.JVMEvent; import com.microsoft.gctoolkit.event.jvm.JVMTermination; import com.microsoft.gctoolkit.event.zgc.ZGCPageAgeSummary; -import com.microsoft.gctoolkit.event.zgc.MinorZGCCycle; import com.microsoft.gctoolkit.event.zgc.ZGCAllocatedSummary; -import com.microsoft.gctoolkit.event.zgc.FullZGCCycle; import com.microsoft.gctoolkit.event.zgc.ZGCGarbageSummary; import com.microsoft.gctoolkit.event.zgc.ZGCHeapCapacitySummary; import com.microsoft.gctoolkit.event.zgc.ZGCLiveSummary; -import com.microsoft.gctoolkit.event.zgc.MajorZGCCycle; import com.microsoft.gctoolkit.event.zgc.OccupancySummary; import com.microsoft.gctoolkit.event.zgc.ZGCCompactedSummary; +import com.microsoft.gctoolkit.event.zgc.ZGCFullCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCYoungCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCOldCollection; import com.microsoft.gctoolkit.event.zgc.ZGCNMethodSummary; import com.microsoft.gctoolkit.event.zgc.ZGCPageSummary; import com.microsoft.gctoolkit.event.zgc.ZGCPhase; import com.microsoft.gctoolkit.event.zgc.ZGCPromotedSummary; import com.microsoft.gctoolkit.event.zgc.ZGCReclaimSummary; import com.microsoft.gctoolkit.event.zgc.ZGCCollectionType; -import com.microsoft.gctoolkit.event.zgc.ZGCCycle; +import com.microsoft.gctoolkit.event.zgc.ZGCCollection; import com.microsoft.gctoolkit.event.zgc.ZGCMarkSummary; import com.microsoft.gctoolkit.event.zgc.ZGCMemoryPoolSummary; import com.microsoft.gctoolkit.event.zgc.ZGCMetaspaceSummary; @@ -44,6 +44,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.HashMap; import java.util.function.BiConsumer; import java.util.logging.Level; import java.util.logging.Logger; @@ -66,17 +67,13 @@ public class ZGCParser extends UnifiedGCLogParser implements ZGCPatterns { private final boolean debugging = Boolean.getBoolean("microsoft.debug"); private final boolean develop = Boolean.getBoolean("microsoft.develop"); - private ZForwardReference forwardReference; + private final ZGCForwardReference[] forwardReferences = new ZGCForwardReference[3]; + private final HashMap gcCauseMap = new HashMap<>(2); - private final long[] markStart = new long[3]; - private final long[] markEnd = new long[3]; - private final long[] relocateStart = new long[3]; - private final long[] relocateEnd = new long[3]; private final long[] heapCapacity = new long[3]; private final MRUQueue> parseRules; - private boolean oldGenHeapStats = false; - private boolean youngGenHeapStats = false; + private boolean genHeapStats = false; //Implement all capture methods { @@ -102,14 +99,13 @@ public class ZGCParser extends UnifiedGCLogParser implements ZGCPatterns { // Generation ("gen") ZGC only options parseRules.put(LOAD_GEN, this::loadGen); parseRules.put(REFERENCE_PROCESSING_GEN, this::referenceProcessingGen); - parseRules.put(END_OF_PHASE_SUMMARY_GEN, this::endOfPhaseMemorySummary); + parseRules.put(END_OF_PHASE_SUMMARY_GEN, this::generationEnd); parseRules.put(PAGES_GEN, this::pageSummary); parseRules.put(FORWARDING_USAGE_GEN, this::forwardingUsage); parseRules.put(AGE_TABLE_GEN, this::ageTable); + parseRules.put(GENERATION_START, this::generationStart); - // Phase change rules - parseRules.put(MARK_OLD_GEN_HEAP_STATS, this::markOldGenHeapStats); - parseRules.put(MARK_YOUNG_GEN_HEAP_STATS, this::markYoungGenHeapStats); + parseRules.put(MARK_GEN_HEAP_STATS, this::markGenHeapStats); } public ZGCParser() {} @@ -123,21 +119,10 @@ public Set eventsProduced() { * This marks the phase we're in for memory stats. Generation ZGC will provide heap capacity * as well as old and young gen capacities. This enables the Young gen phase */ - private void markYoungGenHeapStats(GCLogTrace gcLogTrace, String s) { - this.youngGenHeapStats = true; - this.oldGenHeapStats = false; + private void markGenHeapStats(GCLogTrace gcLogTrace, String s) { + this.genHeapStats = true; } - /** - * This marks the phase we're in for memory stats. Generation ZGC will provide heap capacity - * as well as old and young gen capacities. This enables the Old gen phase - */ - private void markOldGenHeapStats(GCLogTrace gcLogTrace, String s) { - this.youngGenHeapStats = false; - this.oldGenHeapStats = true; - } - - @Override public String getName() { return "ZGC Parser"; @@ -178,38 +163,66 @@ private ZGCForwardReference getForwardRefForPhase(ZGCPhase zgcPhase) { switch (zgcPhase) { // No phase information, legacy ZGC case FULL: - return (ZGCForwardReference) forwardReference; + return forwardReferences[0]; case MAJOR_YOUNG: - return ((ZGCMajorForwardReference)forwardReference).getYoungGeneration(); - case MAJOR_OLD: - return ((ZGCMajorForwardReference)forwardReference).getOldGeneration(); case MINOR_YOUNG: - return ((ZGCMinorForwardReference)forwardReference).getYoungGeneration(); + return forwardReferences[1]; + case MAJOR_OLD: + return forwardReferences[2]; + default: + throw new RuntimeException("Unknown phase " + zgcPhase); } - - // Should never reach (should convert to switch expression) - throw new RuntimeException("Unknown phase " + zgcPhase); } - private void cycleStart(GCLogTrace trace, String s) { - ZGCCollectionType type = ZGCCollectionType.get(trace.getGroup(2)); - - switch (type) { + private void setForwardRefForPhase(ZGCPhase zgcPhase, ZGCForwardReference forwardReference){ + switch (zgcPhase) { + // No phase information, legacy ZGC case FULL: - // FULL, Legacy ZGC - forwardReference = new ZGCForwardReference(getClock(), trace.getLongGroup(1), trace.gcCause(3,0), type, ZGCPhase.FULL); + forwardReferences[0] = forwardReference; break; - case MINOR: - // MINOR, young only collection - forwardReference = new ZGCMinorForwardReference(getClock(), trace.getLongGroup(1), trace.gcCause(3,0), type); + case MAJOR_YOUNG: + case MINOR_YOUNG: + forwardReferences[1] = forwardReference; break; - case MAJOR: - // MAJOR, young and old gen collection - forwardReference = new ZGCMajorForwardReference(getClock(), trace.getLongGroup(1), trace.gcCause(3,0), type); + case MAJOR_OLD: + forwardReferences[2] = forwardReference; break; + default: + throw new RuntimeException("Unknown phase " + zgcPhase); } } + private void cycleStart(GCLogTrace trace, String s) { + ZGCCollectionType type = ZGCCollectionType.get(trace.getGroup(2)); + if(type == ZGCCollectionType.FULL){ + setForwardRefForPhase( + ZGCPhase.FULL, + new ZGCForwardReference(getClock(), trace.getLongGroup(1), trace.gcCause(3,0), type, ZGCPhase.FULL) + ); + } + else { + // The cycle start message gives us the gc cause, which we need to create the GCEvent in generationStart + // When we get a cycle start, store the gc cause for later use + gcCauseMap.put(trace.getLongGroup(1), trace.gcCause(1, 2)); + } + } + + private void generationStart(GCLogTrace trace, String line){ + if(!diary.isGenerationalZGC()){ + LOGGER.severe("generationStart rule was matched, but log file isn't generational ZGC. This should be impossible."); + return; + } + ZGCPhase phase = ZGCPhase.get(trace.getGroup(2)); + long gcId = trace.getLongGroup(1); + GCCause gcCause = gcCauseMap.getOrDefault(gcId, GCCause.UNKNOWN_GCCAUSE); + ZGCForwardReference forwardReference = new ZGCForwardReference(getClock(), gcId, gcCause, ZGCCollectionType.fromPhase(phase), phase); + setForwardRefForPhase( + phase, + forwardReference + ); + } + + private void pausePhase(GCLogTrace trace, String s) { ZGCForwardReference ref = getForwardRefForPhase(trace.getZCollectionPhase()); @@ -421,26 +434,25 @@ private void capacity(GCLogTrace trace, String s) { } } - private void captureAtIndex(GCLogTrace trace, int index) { - // temporary holder of marking info to get set on fwdref - markStart[index] = trace.toKBytes(3); - markEnd[index] = trace.toKBytes(6); - relocateStart[index] = trace.toKBytes(9); - relocateEnd[index] = trace.toKBytes(12); + private void captureAtIndex(GCLogTrace trace, int index, ZGCMemoryPoolSummaryBuilder memoryPoolSummaryBuilder) { + memoryPoolSummaryBuilder.setMarkStart(index, trace.toKBytes(3)); + memoryPoolSummaryBuilder.setMarkEnd(index, trace.toKBytes(6)); + memoryPoolSummaryBuilder.setRelocateStart(index, trace.toKBytes(9)); + memoryPoolSummaryBuilder.setRelocateEnd(index, trace.toKBytes(12)); } private void sizeEntry(GCLogTrace trace, String s) { ZGCPhase phase = trace.getZCollectionPhase(); ZGCForwardReference ref = getForwardRefForPhase(phase); - if (oldGenHeapStats || youngGenHeapStats) { + if (genHeapStats) { if ("Used".equals(trace.getGroup(2))){ OccupancySummary summary = new OccupancySummary( trace.toKBytes(3), trace.toKBytes(6), trace.toKBytes(9), trace.toKBytes(12)); - ref.setUsed(phase, summary); + ref.setGenerationUsedSummary(phase, summary); } else { trace.notYetImplemented(); } @@ -449,16 +461,17 @@ private void sizeEntry(GCLogTrace trace, String s) { switch (trace.getGroup(2)) { case "Capacity": - captureAtIndex(trace, 0); + captureAtIndex(trace, 0, ref.memoryPoolSummaryBuilder); break; case "Free": - captureAtIndex(trace, 1); + captureAtIndex(trace, 1, ref.memoryPoolSummaryBuilder); break; case "Used": - ref.setMarkStart(new ZGCMemoryPoolSummary(markStart[0], markStart[1], trace.toKBytes(3))); - ref.setMarkEnd(new ZGCMemoryPoolSummary(markEnd[0], markEnd[1], trace.toKBytes(6))); - ref.setRelocateStart(new ZGCMemoryPoolSummary(relocateStart[0], relocateStart[1], trace.toKBytes(9))); - ref.setRelocateEnd(new ZGCMemoryPoolSummary(relocateEnd[0], relocateEnd[1], trace.toKBytes(12))); + captureAtIndex(trace, 2, ref.memoryPoolSummaryBuilder); + ref.setMarkStart(ref.memoryPoolSummaryBuilder.buildMarkStart()); + ref.setMarkEnd(ref.memoryPoolSummaryBuilder.buildMarkEnd()); + ref.setRelocateStart(ref.memoryPoolSummaryBuilder.buildRelocateStart()); + ref.setRelocateEnd(ref.memoryPoolSummaryBuilder.buildRelocateEnd()); break; default: LOGGER.warning(trace.getGroup(2) + "not recognized, Heap Occupancy/size is is ignored. Please report this with the GC log"); @@ -510,9 +523,8 @@ private void reclaimedPromoted(GCLogTrace trace, String s) { private void compacted(GCLogTrace trace, String s) { ZGCForwardReference ref = getForwardRefForPhase(trace.getZCollectionPhase()); - // Exit both young and old gen stats, reset for next cycle - this.oldGenHeapStats = false; - this.youngGenHeapStats = false; + // Exit gen stats, reset for next cycle + this.genHeapStats = false; ref.setCompactedSummary( new ZGCCompactedSummary( trace.toKBytes(2) @@ -520,9 +532,10 @@ private void compacted(GCLogTrace trace, String s) { ); } - private void endOfPhaseMemorySummary(GCLogTrace trace, String s) { + private void generationEnd(GCLogTrace trace, String s) { ZGCForwardReference ref = getForwardRefForPhase(trace.getZCollectionPhase()); + genHeapStats = false; ref.setMemorySummary( new ZGCMemorySummary( trace.toKBytes(3), @@ -531,42 +544,24 @@ private void endOfPhaseMemorySummary(GCLogTrace trace, String s) { if (trace.getGroup(9) != null) { ref.setGcDuration(trace.getSeconds(9)); } + + publish(ref.getGCEVent(getClock())); } private void memorySummary(GCLogTrace trace, String s) { - ZGCCollectionType type = ZGCCollectionType.get(trace.getGroup(1)); - switch (type) { - case FULL: - ((ZGCForwardReference)forwardReference).setMemorySummary( + if(diary.isGenerationalZGC()){ + long gcId = trace.getLongGroup(1); + gcCauseMap.remove(gcId); + } else { + ZGCForwardReference forwardReference = getForwardRefForPhase(ZGCPhase.FULL); + forwardReference.setMemorySummary( new ZGCMemorySummary( - trace.toKBytes(3), - trace.toKBytes(6))); - break; - case MINOR: - ((ZGCMinorForwardReference)forwardReference).setMemorySummary( - new ZGCMemorySummary( - trace.toKBytes(3), - trace.toKBytes(6))); - break; - case MAJOR: - ((ZGCMajorForwardReference)forwardReference).setMemorySummary( - new ZGCMemorySummary( - trace.toKBytes(3), - trace.toKBytes(6))); - break; + trace.toKBytes(4), + trace.toKBytes(7))); + publish(forwardReference.getGCEVent(getClock())); } - - // Clean up / reset temp variables - Arrays.fill(markStart, 0L); - Arrays.fill(markEnd, 0L); - Arrays.fill(relocateStart, 0L); - Arrays.fill(relocateEnd, 0L); + // TODO - Get rid of this? Arrays.fill(heapCapacity, 0L); - oldGenHeapStats = false; - youngGenHeapStats = false; - - // TODO: Consider using logging cycle duration instead of timestamps - publish(); } @@ -580,129 +575,51 @@ public void logMissedFirstRecordForEvent(String line) { LOGGER.log(Level.WARNING, "Missing initial record for: {0}", line); } - public void publish() { - publish(forwardReference.getGCEVent(getClock())); - } - public void publish(JVMEvent event) { super.publish(ChannelName.ZGC_PARSER_OUTBOX, event); - forwardReference = null; - } - - private interface ZForwardReference { - GCEvent getGCEVent(DateTimeStamp endTime); } - private static class ZGCMinorForwardReference implements ZForwardReference { - private final DateTimeStamp startTimeStamp; - private final GCCause gcCause; - private final ZGCCollectionType type; - private final long gcId; - private ZGCMemorySummary cycleMemorySummary; - - // Holds single reference to minor collection stats - private ZGCForwardReference youngGeneration; + private static class ZGCMemoryPoolSummaryBuilder { + private final long[] markStart = new long[3]; + private final long[] markEnd = new long[3]; + private final long[] relocateStart = new long[3]; + private final long[] relocateEnd = new long[3]; - public ZGCMinorForwardReference(DateTimeStamp dateTimeStamp, long gcId, GCCause cause, ZGCCollectionType type) { - this.startTimeStamp = dateTimeStamp; - this.gcCause = cause; - this.type = type; - this.gcId = gcId; - - youngGeneration = new ZGCForwardReference(dateTimeStamp, gcId, cause, type, ZGCPhase.MINOR_YOUNG); + public void setMarkStart(int index, long value){ + markStart[index] = value; } - public ZGCForwardReference getYoungGeneration() { - return youngGeneration; + public void setMarkEnd(int index, long value){ + markEnd[index] = value; } - @Override - public GCEvent getGCEVent(DateTimeStamp endTime) { - GarbageCollectionTypes gcType = GarbageCollectionTypes.Unknown; - switch (type) { - case FULL: - gcType = GarbageCollectionTypes.ZGCFull; - break; - case MINOR: - gcType = GarbageCollectionTypes.ZGCMinor; - break; - case MAJOR: - gcType = GarbageCollectionTypes.ZGCMajor; - break; - } - - MinorZGCCycle cycle = new MinorZGCCycle(startTimeStamp, gcType, gcCause, endTime.minus(startTimeStamp)); - cycle.setYoungCycle(youngGeneration.getZGCCycle(endTime)); - cycle.setMemorySummary(cycleMemorySummary); - cycle.setGcId(gcId); - - return cycle; + public void setRelocateStart(int index, long value){ + relocateStart[index] = value; } - public void setMemorySummary(ZGCMemorySummary cycleMemorySummary) { - this.cycleMemorySummary = cycleMemorySummary; + public void setRelocateEnd(int index, long value){ + relocateEnd[index] = value; } - } - - private static class ZGCMajorForwardReference implements ZForwardReference { - private final DateTimeStamp startTimeStamp; - private final GCCause gcCause; - private final ZGCCollectionType type; - private final long gcId; - private ZGCMemorySummary cycleMemorySummary; - - // Holds two references to minor and major collection stats - private final ZGCForwardReference youngGeneration; - private final ZGCForwardReference oldGeneration; - public ZGCMajorForwardReference(DateTimeStamp dateTimeStamp, long gcId, GCCause cause, ZGCCollectionType type) { - this.startTimeStamp = dateTimeStamp; - this.gcCause = cause; - this.type = type; - this.gcId = gcId; - - youngGeneration = new ZGCForwardReference(dateTimeStamp, gcId, cause, type, ZGCPhase.MAJOR_YOUNG); - oldGeneration = new ZGCForwardReference(dateTimeStamp, gcId, cause, type, ZGCPhase.MAJOR_OLD); + public ZGCMemoryPoolSummary buildMarkStart(){ + return new ZGCMemoryPoolSummary(markStart[0], markStart[1], markStart[2]); } - public ZGCForwardReference getYoungGeneration() { - return youngGeneration; + public ZGCMemoryPoolSummary buildMarkEnd(){ + return new ZGCMemoryPoolSummary(markEnd[0], markEnd[1], markEnd[2]); } - public ZGCForwardReference getOldGeneration() { - return oldGeneration; + public ZGCMemoryPoolSummary buildRelocateStart(){ + return new ZGCMemoryPoolSummary(relocateStart[0], relocateStart[1], relocateStart[2]); } - public void setMemorySummary(ZGCMemorySummary cycleMemorySummary) { - this.cycleMemorySummary = cycleMemorySummary; + public ZGCMemoryPoolSummary buildRelocateEnd(){ + return new ZGCMemoryPoolSummary(relocateEnd[0], relocateEnd[1], relocateEnd[2]); } - @Override - public GCEvent getGCEVent(DateTimeStamp endTime) { - GarbageCollectionTypes gcType = GarbageCollectionTypes.Unknown; - switch (type) { - case FULL: - gcType = GarbageCollectionTypes.ZGCFull; - break; - case MINOR: - gcType = GarbageCollectionTypes.ZGCMinor; - break; - case MAJOR: - gcType = GarbageCollectionTypes.ZGCMajor; - break; - } - - MajorZGCCycle cycle = new MajorZGCCycle(startTimeStamp, gcType, gcCause, endTime.minus(startTimeStamp)); - cycle.setYoungCycle(youngGeneration.getZGCCycle(endTime)); - cycle.setOldCycle(oldGeneration.getZGCCycle(endTime)); - cycle.setMemorySummary(cycleMemorySummary); - cycle.setGcId(gcId); - - return cycle; - } } - private static class ZGCForwardReference implements ZForwardReference { + private static class ZGCForwardReference { private final DateTimeStamp startTimeStamp; private final GCCause gcCause; private final ZGCCollectionType type; @@ -765,7 +682,7 @@ private static class ZGCForwardReference implements ZForwardReference { private ZGCPromotedSummary promotedSummary; private ZGCCompactedSummary compactedSummary; private Double gcDuration; - private OccupancySummary usedOccupancySummary; + private OccupancySummary generationUsedSummary; private ZGCReferenceSummary softRefSummary; private ZGCReferenceSummary weakRefSummary; private ZGCReferenceSummary finalRefSummary; @@ -776,6 +693,7 @@ private static class ZGCForwardReference implements ZForwardReference { private ZGCPageSummary largePageSummary; private long forwardingUsage; private List ageTableSummary; + private final ZGCMemoryPoolSummaryBuilder memoryPoolSummaryBuilder; public ZGCForwardReference(DateTimeStamp dateTimeStamp, long gcId, GCCause cause, ZGCCollectionType type, ZGCPhase phase) { this.startTimeStamp = dateTimeStamp; @@ -783,37 +701,30 @@ public ZGCForwardReference(DateTimeStamp dateTimeStamp, long gcId, GCCause cause this.gcCause = cause; this.type = type; this.phase = phase; + this.memoryPoolSummaryBuilder = new ZGCMemoryPoolSummaryBuilder(); } - @Override public GCEvent getGCEVent(DateTimeStamp endTime) { - GarbageCollectionTypes gcType = GarbageCollectionTypes.Unknown; - switch (type) { + ZGCCollection cycle; + double duration = (gcDuration != null) ? gcDuration : endTime.minus(startTimeStamp); + + switch (phase) { case FULL: - gcType = GarbageCollectionTypes.ZGCFull; + cycle = new ZGCFullCollection(startTimeStamp, GarbageCollectionTypes.ZGCFull, gcCause, duration); break; - case MINOR: - gcType = GarbageCollectionTypes.ZGCMinor; + case MINOR_YOUNG: + cycle = new ZGCYoungCollection(startTimeStamp, GarbageCollectionTypes.ZGCMinorYoung, gcCause, duration); break; - case MAJOR: - gcType = GarbageCollectionTypes.ZGCMajor; + case MAJOR_YOUNG: + cycle = new ZGCYoungCollection(startTimeStamp, GarbageCollectionTypes.ZGCMajorYoung, gcCause, duration); break; + case MAJOR_OLD: + cycle = new ZGCOldCollection(startTimeStamp, GarbageCollectionTypes.ZGCMajorOld, gcCause, duration); + break; + default: + throw new RuntimeException("Unknown GC phase: " + phase); } - // Duration recorded by GC - FullZGCCycle fullZGCCycle; - ZGCCycle delegate = getZGCCycle(endTime); - if (gcDuration != null){ - fullZGCCycle = new FullZGCCycle(startTimeStamp, gcType, gcCause, gcDuration, delegate); - } else { - fullZGCCycle = new FullZGCCycle(startTimeStamp, gcType, gcCause, endTime.minus(startTimeStamp), delegate); - } - - return fullZGCCycle; - } - - public ZGCCycle getZGCCycle(DateTimeStamp endTime) { - ZGCCycle cycle = new ZGCCycle(); cycle.setGcId(gcId); cycle.setType(type); cycle.setPhase(phase); @@ -835,7 +746,7 @@ public ZGCCycle getZGCCycle(DateTimeStamp endTime) { cycle.setConcurrentRemapRoots(concurrentRemapRootsStart, concurrentRemapRootsDuration); cycle.setPromotedSummary(promotedSummary); cycle.setCompactedSummary(compactedSummary); - cycle.setusedOccupancySummary(usedOccupancySummary); + cycle.setGenerationUsedSummary(generationUsedSummary); cycle.setSoftRefSummary(softRefSummary); cycle.setWeakRefSummary(weakRefSummary); cycle.setFinalRefSummary(finalRefSummary); @@ -1067,7 +978,7 @@ public void setGcDuration(double gcDuration) { this.gcDuration = gcDuration; } - public void setUsed(ZGCPhase phase, OccupancySummary summary) { + public void setGenerationUsedSummary(ZGCPhase phase, OccupancySummary summary) { switch (phase) { case FULL: // does not apply to non generational GC @@ -1075,7 +986,7 @@ public void setUsed(ZGCPhase phase, OccupancySummary summary) { case MAJOR_YOUNG: case MAJOR_OLD: case MINOR_YOUNG: - this.usedOccupancySummary = summary; + this.generationUsedSummary = summary; break; } } diff --git a/parser/src/main/java/com/microsoft/gctoolkit/parser/jvm/UnifiedDiarizer.java b/parser/src/main/java/com/microsoft/gctoolkit/parser/jvm/UnifiedDiarizer.java index 094292bb..30743a07 100644 --- a/parser/src/main/java/com/microsoft/gctoolkit/parser/jvm/UnifiedDiarizer.java +++ b/parser/src/main/java/com/microsoft/gctoolkit/parser/jvm/UnifiedDiarizer.java @@ -173,21 +173,26 @@ private void extractTagsAndLevels(Decorators decorators) { */ private void discoverCollector(String line) { - if ( ZGC_TAG.parse(line) != null || CYCLE_START.parse(line) != null) { + if (CYCLE_START.parse(line) != null) { + String cycleType = CYCLE_START.parse(line).getGroup(2); diary.setTrue(ZGC); - diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, G1GC, RSET_STATS, SHENANDOAH, CMS_DEBUG_LEVEL_1, PRE_JDK70_40, JDK70, JDK80, TENURING_DISTRIBUTION, MAX_TENURING_THRESHOLD_VIOLATION, TLAB_DATA, PRINT_PROMOTION_FAILURE, PRINT_FLS_STATISTICS); + if(cycleType.equals("Minor") || cycleType.equals("Major")) + diary.setTrue(GENERATIONAL_ZGC); + else + diary.setFalse(GENERATIONAL_ZGC); + diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, G1GC, RSET_STATS, SHENANDOAH, CMS_DEBUG_LEVEL_1, PRE_JDK70_40, JDK70, JDK80, TENURING_DISTRIBUTION, MAX_TENURING_THRESHOLD_VIOLATION, TLAB_DATA, PRINT_PROMOTION_FAILURE, PRINT_FLS_STATISTICS, ADAPTIVE_SIZING); return; } if ( SHENANDOAH_TAG.parse(line) != null) { diary.setTrue(SHENANDOAH); - diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, G1GC, RSET_STATS, ZGC, CMS_DEBUG_LEVEL_1, PRE_JDK70_40, JDK70, JDK80, TENURING_DISTRIBUTION, MAX_TENURING_THRESHOLD_VIOLATION, TLAB_DATA, PRINT_PROMOTION_FAILURE, PRINT_FLS_STATISTICS, PRINT_HEAP_AT_GC); + diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, G1GC, RSET_STATS, ZGC, CMS_DEBUG_LEVEL_1, PRE_JDK70_40, JDK70, JDK80, TENURING_DISTRIBUTION, MAX_TENURING_THRESHOLD_VIOLATION, TLAB_DATA, PRINT_PROMOTION_FAILURE, PRINT_FLS_STATISTICS, PRINT_HEAP_AT_GC, GENERATIONAL_ZGC); return; } if (G1_TAG.parse(line) != null || line.contains("G1 Evacuation Pause") || (line.contains("Humongous regions: "))) { diary.setTrue(G1GC); - diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, ZGC, SHENANDOAH, CMS_DEBUG_LEVEL_1, PRE_JDK70_40, JDK70, JDK80, TLAB_DATA, PRINT_PROMOTION_FAILURE, PRINT_FLS_STATISTICS); + diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, ZGC, SHENANDOAH, CMS_DEBUG_LEVEL_1, PRE_JDK70_40, JDK70, JDK80, TLAB_DATA, PRINT_PROMOTION_FAILURE, PRINT_FLS_STATISTICS, GENERATIONAL_ZGC); return; } @@ -195,7 +200,7 @@ private void discoverCollector(String line) { PARNEW_TAG.parse(line) != null || line.contains("ParNew")) { diary.setTrue(PARNEW, CMS); - diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, ICMS, CMS_DEBUG_LEVEL_1, G1GC, ZGC, SHENANDOAH, PRE_JDK70_40, JDK70, JDK80, RSET_STATS); + diary.setFalse(DEFNEW, SERIAL, PARALLELGC, PARALLELOLDGC, ICMS, CMS_DEBUG_LEVEL_1, G1GC, ZGC, SHENANDOAH, PRE_JDK70_40, JDK70, JDK80, RSET_STATS, GENERATIONAL_ZGC); return; } @@ -203,13 +208,13 @@ private void discoverCollector(String line) { line.contains("ParOldGen") || line.contains("PSYoungGen")) { diary.setTrue(PARALLELGC, PARALLELOLDGC, GC_CAUSE); - diary.setFalse(DEFNEW, SERIAL, PARNEW, CMS, ICMS, CMS_DEBUG_LEVEL_1, G1GC, ZGC, SHENANDOAH, PRE_JDK70_40, JDK70, JDK80, RSET_STATS); + diary.setFalse(DEFNEW, SERIAL, PARNEW, CMS, ICMS, CMS_DEBUG_LEVEL_1, G1GC, ZGC, SHENANDOAH, PRE_JDK70_40, JDK70, JDK80, RSET_STATS, GENERATIONAL_ZGC); return; } if (SERIAL_TAG.parse(line) != null || line.contains("DefNew")) { diary.setTrue(DEFNEW, SERIAL, GC_CAUSE); - diary.setFalse(PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, CMS_DEBUG_LEVEL_1, G1GC, ZGC, SHENANDOAH, PRE_JDK70_40, JDK70, JDK80, RSET_STATS); + diary.setFalse(PARALLELGC, PARALLELOLDGC, PARNEW, CMS, ICMS, CMS_DEBUG_LEVEL_1, G1GC, ZGC, SHENANDOAH, PRE_JDK70_40, JDK70, JDK80, RSET_STATS, GENERATIONAL_ZGC); return; } } diff --git a/parser/src/main/java/com/microsoft/gctoolkit/parser/unified/ZGCPatterns.java b/parser/src/main/java/com/microsoft/gctoolkit/parser/unified/ZGCPatterns.java index 0688540e..a744aa64 100644 --- a/parser/src/main/java/com/microsoft/gctoolkit/parser/unified/ZGCPatterns.java +++ b/parser/src/main/java/com/microsoft/gctoolkit/parser/unified/ZGCPatterns.java @@ -20,6 +20,12 @@ public interface ZGCPatterns extends UnifiedPatterns { //[3.558s][info ][gc,start ] GC(3) Garbage Collection (Warmup) GCParseRule CYCLE_START = new GCParseRule("CYCLE_START", "GC\\(" + GenericTokens.INT + "\\) (Garbage|Major|Minor) Collection " + GenericTokens.GC_CAUSE + "$"); + // [2024-11-19T09:48:57.431-0600][info ][gc,phases ] GC(6) Y: Young Generation (Promote All) + // [2024-11-19T09:48:42.508-0600][info ][gc,phases ] GC(3) Y: Young Generation + // [2024-11-19T09:48:31.984-0600][info][gc,phases ] GC(0) O: Old Generation + // [2024-11-19T09:48:52.855-0600][info ][gc,phases ] GC(5) y: Young Generation + GCParseRule GENERATION_START = new GCParseRule("Generation Start", "GC\\(" + GenericTokens.INT + "\\) " + OPT_GEN + "(Young|Old) Generation(?: \\([a-zA-Z ]+\\))?$"); + //[3.559s][info ][gc,phases ] GC(3) Pause Mark Start 0.460ms //[3.574s][info ][gc,phases ] GC(3) Pause Mark End 0.830ms //[3.583s][info ][gc,phases ] GC(3) Pause Relocate Start 0.794ms @@ -101,11 +107,8 @@ public interface ZGCPatterns extends UnifiedPatterns { // Gen ZGC // [info][gc,heap ] GC(2) O: Old Generation Statistics: - GCParseRule MARK_OLD_GEN_HEAP_STATS = new GCParseRule("Mark Old Gen Stats", OPT_GEN + "Old Generation Statistics"); - - // Gen ZGC // [info][gc,heap ] GC(4) Y: Young Generation Statistics: - GCParseRule MARK_YOUNG_GEN_HEAP_STATS = new GCParseRule("Mark Young Gen Stats", OPT_GEN + "Young Generation Statistics"); + GCParseRule MARK_GEN_HEAP_STATS = new GCParseRule("Mark Gen Stats", OPT_GEN + "(Old|Young) Generation Statistics"); //[3.596s][info ][gc,heap ] GC(3) Live: - 8M (0%) 8M (0%) 8M (0%) - - //[3.596s][info ][gc,heap ] GC(3) Allocated: - 172M (4%) 172M (4%) 376M (9%) - - @@ -122,14 +125,15 @@ public interface ZGCPatterns extends UnifiedPatterns { // [info][gc,phases ] GC(58) Y: Young Generation 16052M(44%)->3022M(8%) 1.017s // [info][gc,phases ] GC(58) O: Old Generation 3022M(8%)->5486M(15%) 1.757s - GCParseRule END_OF_PHASE_SUMMARY_GEN = new GCParseRule("End of Phase Summary", OPT_GEN + "(Old|Young) Generation " + MEMORY_PERCENT + "->" + MEMORY_PERCENT + "\\s*" + PAUSE_TIME); + // [2024-11-19T09:49:02.950-0600][info ][gc,phases ] GC(6) Y: Young Generation (Promote All) 13184M(80%)->16384M(100%) 5.519s + GCParseRule END_OF_PHASE_SUMMARY_GEN = new GCParseRule("End of Phase Summary", OPT_GEN + "(Old|Young) Generation(?: \\([a-zA-Z ]+\\))? " + MEMORY_PERCENT + "->" + MEMORY_PERCENT + "\\s*" + PAUSE_TIME); //[3.596s][info ][gc ] GC(3) Garbage Collection (Warmup) 894M(22%)->186M(5%) // or // Gen GC //[3.596s][info][gc ] GC(7) Minor Collection (Allocation Rate) 14720M(40%)->2054M(6%) 0.689s - GCParseRule MEMORY_SUMMARY = new GCParseRule("Memory Summary", "(Garbage|Minor|Major) Collection " + GenericTokens.GC_CAUSE + MEMORY_PERCENT + "->" + MEMORY_PERCENT + "(?:\\s*" + PAUSE_TIME + ")?"); + GCParseRule MEMORY_SUMMARY = new GCParseRule("Memory Summary", "GC\\("+ GenericTokens.INT + "\\)\\s*(Garbage|Minor|Major) Collection " + GenericTokens.GC_CAUSE + MEMORY_PERCENT + "->" + MEMORY_PERCENT + "(?:\\s*" + PAUSE_TIME + ")?"); /* todo: capture and report on these log entries diff --git a/parser/src/test/java/com/microsoft/gctoolkit/parser/GenerationalZGCParserTest.java b/parser/src/test/java/com/microsoft/gctoolkit/parser/GenerationalZGCParserTest.java index 99efe2e9..1cd36d8d 100644 --- a/parser/src/test/java/com/microsoft/gctoolkit/parser/GenerationalZGCParserTest.java +++ b/parser/src/test/java/com/microsoft/gctoolkit/parser/GenerationalZGCParserTest.java @@ -2,24 +2,9 @@ // Licensed under the MIT License. package com.microsoft.gctoolkit.parser; +import com.microsoft.gctoolkit.event.GarbageCollectionTypes; import com.microsoft.gctoolkit.event.jvm.JVMEvent; -import com.microsoft.gctoolkit.event.zgc.MajorZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MinorZGCCycle; -import com.microsoft.gctoolkit.event.zgc.OccupancySummary; -import com.microsoft.gctoolkit.event.zgc.ZGCPageAgeSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCAllocatedSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCCompactedSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCCycle; -import com.microsoft.gctoolkit.event.zgc.ZGCGarbageSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCHeapCapacitySummary; -import com.microsoft.gctoolkit.event.zgc.ZGCLiveSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCMemoryPoolSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCMemorySummary; -import com.microsoft.gctoolkit.event.zgc.ZGCMetaspaceSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCPageSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCPromotedSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCReclaimSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCReferenceSummary; +import com.microsoft.gctoolkit.event.zgc.*; import com.microsoft.gctoolkit.jvm.Diarizer; import com.microsoft.gctoolkit.parser.jvm.UnifiedDiarizer; import com.microsoft.gctoolkit.time.DateTimeStamp; @@ -138,21 +123,20 @@ public void testZgcMajorCycle() { }; - List singleCycle = feedParser(eventLogEntries); + List singleYoungSingleOld = feedParser(eventLogEntries); try { - assertEquals(1, singleCycle.size()); - MajorZGCCycle zgc = (MajorZGCCycle) singleCycle.get(0); + assertEquals(2, singleYoungSingleOld.size()); - assertEquals(zgc.getGcId(), 1L); + ZGCYoungCollection young = (ZGCYoungCollection) singleYoungSingleOld.get(0); - assertEquals(toInt(0.1039d,1000), toInt(zgc.getDuration(),1000)); - assertEquals(toInt(1.739307979476E9, 1000), toInt(zgc.getDateTimeStamp().getTimeStamp(), 1000)); - assertEquals("Metadata GC Threshold", zgc.getGCCause().getLabel()); + assertEquals(young.getGcId(), 1L); + assertEquals(toInt(0.075d, 1000), toInt(young.getDuration(),1000)); + assertEquals(toInt(1.739307979476E9, 1000), toInt(young.getDateTimeStamp().getTimeStamp(), 1000)); + assertEquals("Metadata GC Threshold", young.getGCCause().getLabel()); /* * Young Phase Checks */ - ZGCCycle young = zgc.getYoungCycle(); // Durations assertTrue(checkDateTimeStampMatch("2025-02-11T13:06:19.476-0800", 0.023, young.getPauseMarkStartTimeStamp())); assertTrue(checkDateTimeStampMatch("2025-02-11T13:06:19.534-0800", 57.581, young.getConcurrentMarkTimeStamp())); @@ -182,7 +166,7 @@ public void testZgcMajorCycle() { assertTrue(checkZGCMetaSpaceSummary(young.getMetaspaceSummary(),36, 37, 1088)); - assertTrue(checkUsedSummary(young.getUsedOccupancySummary(), 296, 308, 240, 76)); + assertTrue(checkUsedSummary(young.getGenerationUsedSummary(), 296, 308, 240, 76)); assertTrue(checkLiveSummary(young.getLiveSummary(), 24, 24, 24)); assertTrue(checkGarbageSummary(young.getGarbageSummary(), 271, 203, 31)); assertTrue(checkAllocatedSummary(young.getAllocatedSummary(), 12, 12, 19)); @@ -220,7 +204,13 @@ public void testZgcMajorCycle() { /* * Old Phase Checks */ - ZGCCycle old = zgc.getOldCycle(); + ZGCOldCollection old = (ZGCOldCollection) singleYoungSingleOld.get(1); + + assertEquals(old.getGcId(), 1L); + assertEquals(toInt(0.029d, 1000), toInt(old.getDuration(),1000)); + assertEquals(toInt(1.739307979476E9, 1000), toInt(old.getDateTimeStamp().getTimeStamp(), 1000)); + assertEquals("Metadata GC Threshold", old.getGCCause().getLabel()); + // Durations assertTrue(checkDateTimeStampMatch("2025-02-11T13:06:19.553-0800", 1.286, old.getConcurrentMarkTimeStamp())); assertTrue(checkDateTimeStampMatch("2025-02-11T13:06:19.553-0800", 0.017, old.getPauseMarkEndTimeStamp())); @@ -263,7 +253,7 @@ public void testZgcMajorCycle() { assertEquals(125 * 1024, old.getForwardingUsage()); - assertTrue(checkUsedSummary(old.getUsedOccupancySummary(), 0, 0, 0, 0)); + assertTrue(checkUsedSummary(old.getGenerationUsedSummary(), 0, 0, 0, 0)); assertTrue(checkLiveSummary(old.getLiveSummary(), 0, 0, 0)); assertTrue(checkGarbageSummary(old.getGarbageSummary(), 0, 0, 0)); assertTrue(checkAllocatedSummary(old.getAllocatedSummary(), 0, 0, 0)); @@ -348,18 +338,14 @@ public void testZgcMinorCycle() { List singleCycle = feedParser(eventLogEntries); try { assertEquals(1, singleCycle.size()); - MinorZGCCycle zgc = (MinorZGCCycle) singleCycle.get(0); + ZGCYoungCollection young = (ZGCYoungCollection) singleCycle.get(0); - assertEquals(zgc.getGcId(), 7L); + assertEquals(young.getGcId(), 7L); - assertEquals(toInt(0.690d,1000), toInt(zgc.getDuration(),1000)); - assertTrue(checkDateTimeStampMatch("2025-02-11T13:07:12.566-0800", 0, zgc.getDateTimeStamp())); - assertEquals("Allocation Rate", zgc.getGCCause().getLabel()); + assertEquals(toInt(0.689d,1000), toInt(young.getDuration(),1000)); + assertTrue(checkDateTimeStampMatch("2025-02-11T13:07:12.566-0800", 0, young.getDateTimeStamp())); + assertEquals("Allocation Rate", young.getGCCause().getLabel()); - /* - * Young Phase Checks - */ - ZGCCycle young = zgc.getYoungCycle(); // Durations assertTrue(checkDateTimeStampMatch("2025-02-11T13:07:12.566-0800", 0.025, young.getPauseMarkStartTimeStamp())); assertTrue(checkDateTimeStampMatch("2025-02-11T13:07:13.042-0800", 475.464, young.getConcurrentMarkTimeStamp())); @@ -389,7 +375,7 @@ public void testZgcMinorCycle() { assertTrue(checkZGCMetaSpaceSummary(young.getMetaspaceSummary(),100, 101, 1152)); - assertTrue(checkUsedSummary(young.getUsedOccupancySummary(), 14132, 14900, 12364, 1466)); + assertTrue(checkUsedSummary(young.getGenerationUsedSummary(), 14132, 14900, 12364, 1466)); assertTrue(checkLiveSummary(young.getLiveSummary(), 120, 120, 120)); assertTrue(checkGarbageSummary(young.getGarbageSummary(), 14011, 11457, 2)); assertTrue(checkAllocatedSummary(young.getAllocatedSummary(), 768, 786, 1343)); @@ -429,6 +415,225 @@ public void testZgcMinorCycle() { } } + @Test + public void testMultipleConcurrentCycles() { + String[] eventLogEntries = { + "[2024-11-19T09:48:42.508-0600][info ][gc ] GC(3) Major Collection (Warmup)", + "[2024-11-19T09:48:42.508-0600][info ][gc,task ] GC(3) Using 3 Workers for Young Generation", + "[2024-11-19T09:48:42.508-0600][info ][gc,task ] GC(3) Using 1 Workers for Old Generation", + "[2024-11-19T09:48:42.508-0600][info ][gc,phases ] GC(3) Y: Young Generation", + "[2024-11-19T09:48:42.509-0600][info ][gc,phases ] GC(3) Y: Pause Mark Start (Major) 0.005ms", + "[2024-11-19T09:48:45.908-0600][info ][gc,phases ] GC(3) Y: Concurrent Mark 3399.497ms", + "[2024-11-19T09:48:45.908-0600][info ][gc,phases ] GC(3) Y: Pause Mark End 0.016ms", + "[2024-11-19T09:48:45.908-0600][info ][gc,phases ] GC(3) Y: Concurrent Mark Free 0.000ms", + "[2024-11-19T09:48:45.908-0600][info ][gc,phases ] GC(3) Y: Concurrent Reset Relocation Set 0.054ms", + "[2024-11-19T09:48:45.910-0600][info ][gc,reloc ] GC(3) Y: Using tenuring threshold: 4 (Computed)", + "[2024-11-19T09:48:46.044-0600][info ][gc,phases ] GC(3) Y: Concurrent Select Relocation Set 135.227ms", + "[2024-11-19T09:48:46.045-0600][info ][gc,phases ] GC(3) Y: Pause Relocate Start 0.024ms", + "[2024-11-19T09:48:47.878-0600][info ][gc,phases ] GC(3) Y: Concurrent Relocate 1829.530ms", + "[2024-11-19T09:48:47.878-0600][info ][gc,alloc ] GC(3) Y: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:47.878-0600][info ][gc,alloc ] GC(3) Y: Allocation Stalls: 0 38 0 0", + "[2024-11-19T09:48:47.879-0600][info ][gc,load ] GC(3) Y: Load: 22.08 (184%) / 8.18 (68%) / 4.99 (42%)", + "[2024-11-19T09:48:47.879-0600][info ][gc,mmu ] GC(3) Y: MMU: 2ms/98.8%, 5ms/99.5%, 10ms/99.8%, 20ms/99.9%, 50ms/99.9%, 100ms/100.0%", + "[2024-11-19T09:48:47.879-0600][info ][gc,marking ] GC(3) Y: Mark: 2 stripe(s), 10 proactive flush(es), 1 terminate flush(es), 0 completion(s), 0 continuation(s)", + "[2024-11-19T09:48:47.879-0600][info ][gc,marking ] GC(3) Y: Mark Stack Usage: 32M", + "[2024-11-19T09:48:47.879-0600][info ][gc,nmethod ] GC(3) Y: NMethods: 5348 registered, 0 unregistered", + "[2024-11-19T09:48:47.879-0600][info ][gc,metaspace] GC(3) Y: Metaspace: 45M used, 46M committed, 1088M reserved", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Candidates Selected In-Place Size Empty Relocated", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Small Pages: 4449 2921 0 8898M 664M 1107M", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Medium Pages: 2 1 0 64M 0M 0M", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Large Pages: 0 0 0 0M 0M 0M", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Forwarding Usage: 600M", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Age Table:", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Live Garbage Small Medium Large", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Eden 1710M (10%) 6677M (41%) 4194 / 2878 0 / 0 0 / 0", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Survivor 1 266M (2%) 137M (1%) 202 / 39 0 / 0 0 / 0", + "[2024-11-19T09:48:47.879-0600][info ][gc,reloc ] GC(3) Y: Survivor 2 77M (0%) 44M (0%) 45 / 3 1 / 1 0 / 0", + "[2024-11-19T09:48:47.883-0600][info ][gc,reloc ] GC(3) Y: Survivor 3 12M (0%) 35M (0%) 8 / 1 1 / 0 0 / 0", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Min Capacity: 8M(0%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Soft Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Heap Statistics:", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Mark Start Mark End Relocate Start Relocate End High Low", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Capacity: 8962M (55%) 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%) 8962M (55%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Free: 7422M (45%) 0M (0%) 468M (3%) 3080M (19%) 7422M (45%) 0M (0%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Used: 8962M (55%) 16384M (100%) 15916M (97%) 13304M (81%) 16384M (100%) 8962M (55%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Young Generation Statistics:", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Used: 8962M (55%) 16384M (100%) 15916M (97%) 13304M (81%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Live: - 2067M (13%) 2067M (13%) 2067M (13%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Garbage: - 6894M (42%) 6230M (38%) 53M (0%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Allocated: - 7422M (45%) 7618M (46%) 11183M (68%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Reclaimed: - - 664M (4%) 6841M (42%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Promoted: - - 0M (0%) 0M (0%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,heap ] GC(3) Y: Compacted: - - - 1768M (11%)", + "[2024-11-19T09:48:47.883-0600][info ][gc,phases ] GC(3) Y: Young Generation 8962M(55%)->13304M(81%) 5.370s", + "[2024-11-19T09:48:47.883-0600][info ][gc,phases ] GC(3) O: Old Generation", + "[2024-11-19T09:48:47.883-0600][info ][gc ] GC(4) Minor Collection (Allocation Stall)", + "[2024-11-19T09:48:47.883-0600][info ][gc,task ] GC(4) Using 3 Workers for Young Generation", + "[2024-11-19T09:48:47.883-0600][info ][gc,phases ] GC(4) y: Young Generation", + "[2024-11-19T09:48:47.902-0600][info ][gc,phases ] GC(4) y: Pause Mark Start 0.009ms", + "[2024-11-19T09:48:48.014-0600][info ][gc,phases ] GC(3) O: Concurrent Mark 131.401ms", + "[2024-11-19T09:48:48.051-0600][info ][gc,phases ] GC(3) O: Pause Mark End 0.011ms", + "[2024-11-19T09:48:48.051-0600][info ][gc,phases ] GC(3) O: Concurrent Mark Free 0.001ms", + "[2024-11-19T09:48:48.088-0600][info ][gc,phases ] GC(3) O: Concurrent Process Non-Strong 37.017ms", + "[2024-11-19T09:48:48.088-0600][info ][gc,phases ] GC(3) O: Concurrent Reset Relocation Set 0.000ms", + "[2024-11-19T09:48:48.091-0600][info ][gc,phases ] GC(3) O: Concurrent Select Relocation Set 2.566ms", + "[2024-11-19T09:48:50.579-0600][info ][gc,phases ] GC(4) y: Concurrent Mark 2673.028ms", + "[2024-11-19T09:48:50.579-0600][info ][gc,phases ] GC(4) y: Pause Mark End 0.009ms", + "[2024-11-19T09:48:50.579-0600][info ][gc,phases ] GC(4) y: Concurrent Mark Free 0.000ms", + "[2024-11-19T09:48:50.579-0600][info ][gc,phases ] GC(4) y: Concurrent Reset Relocation Set 0.205ms", + "[2024-11-19T09:48:50.580-0600][info ][gc,reloc ] GC(4) y: Using tenuring threshold: 2 (Computed)", + "[2024-11-19T09:48:50.707-0600][info ][gc,phases ] GC(4) y: Concurrent Select Relocation Set 128.026ms", + "[2024-11-19T09:48:50.709-0600][info ][gc,phases ] GC(4) y: Pause Relocate Start 0.013ms", + "[2024-11-19T09:48:52.806-0600][info ][gc,phases ] GC(4) y: Concurrent Relocate 2096.795ms", + "[2024-11-19T09:48:52.809-0600][info ][gc,alloc ] GC(4) y: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:52.809-0600][info ][gc,alloc ] GC(4) y: Allocation Stalls: 0 37 54 0", + "[2024-11-19T09:48:52.809-0600][info ][gc,load ] GC(4) y: Load: 24.64 (205%) / 8.94 (75%) / 5.27 (44%)", + "[2024-11-19T09:48:52.809-0600][info ][gc,mmu ] GC(4) y: MMU: 2ms/98.8%, 5ms/99.5%, 10ms/99.8%, 20ms/99.9%, 50ms/99.9%, 100ms/100.0%", + "[2024-11-19T09:48:52.809-0600][info ][gc,marking ] GC(4) y: Mark: 2 stripe(s), 10 proactive flush(es), 1 terminate flush(es), 0 completion(s), 0 continuation(s)", + "[2024-11-19T09:48:52.809-0600][info ][gc,marking ] GC(4) y: Mark Stack Usage: 32M", + "[2024-11-19T09:48:52.809-0600][info ][gc,nmethod ] GC(4) y: NMethods: 5329 registered, 373 unregistered", + "[2024-11-19T09:48:52.809-0600][info ][gc,metaspace] GC(4) y: Metaspace: 46M used, 46M committed, 1088M reserved", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Candidates Selected In-Place Size Empty Relocated", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Small Pages: 6654 4106 13 13308M 402M 1531M", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Medium Pages: 2 1 1 64M 0M 0M", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Large Pages: 0 0 0 0M 0M 0M", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Forwarding Usage: 841M", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Age Table:", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Live Garbage Small Medium Large", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Eden 2373M (14%) 8800M (54%) 5587 / 4007 0 / 0 0 / 0", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Survivor 1 1635M (10%) 84M (1%) 860 / 7 0 / 0 0 / 0", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Survivor 2 113M (1%) 194M (1%) 154 / 87 0 / 0 0 / 0", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Survivor 3 76M (0%) 45M (0%) 45 / 3 1 / 1 0 / 0", + "[2024-11-19T09:48:52.809-0600][info ][gc,reloc ] GC(4) y: Survivor 4 12M (0%) 35M (0%) 8 / 2 1 / 0 0 / 0", + "[2024-11-19T09:48:52.809-0600][info ][gc,heap ] GC(4) y: Min Capacity: 8M(0%)", + "[2024-11-19T09:48:52.809-0600][info ][gc,heap ] GC(4) y: Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:52.813-0600][info ][gc,heap ] GC(4) y: Soft Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:52.813-0600][info ][gc,heap ] GC(4) y: Heap Statistics:", + "[2024-11-19T09:48:52.813-0600][info ][gc,heap ] GC(4) y: Mark Start Mark End Relocate Start Relocate End High Low", + "[2024-11-19T09:48:52.813-0600][info ][gc,heap ] GC(4) y: Capacity: 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%)", + "[2024-11-19T09:48:52.817-0600][info ][gc,heap ] GC(4) y: Free: 3012M (18%) 0M (0%) 0M (0%) 730M (4%) 4170M (25%) 0M (0%)", + "[2024-11-19T09:48:52.817-0600][info ][gc,heap ] GC(4) y: Used: 13372M (82%) 16384M (100%) 16384M (100%) 15654M (96%) 16384M (100%) 12214M (75%)", + "[2024-11-19T09:48:52.817-0600][info ][gc,heap ] GC(4) y: Young Generation Statistics:", + "[2024-11-19T09:48:52.817-0600][info ][gc,heap ] GC(4) y: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:52.821-0600][info ][gc,heap ] GC(4) y: Used: 13372M (82%) 16384M (100%) 16260M (99%) 15400M (94%)", + "[2024-11-19T09:48:52.821-0600][info ][gc,heap ] GC(4) y: Live: - 4210M (26%) 4105M (25%) 4009M (24%)", + "[2024-11-19T09:48:52.821-0600][info ][gc,heap ] GC(4) y: Garbage: - 9161M (56%) 8740M (53%) 87M (1%)", + "[2024-11-19T09:48:52.821-0600][info ][gc,heap ] GC(4) y: Allocated: - 3012M (18%) 3414M (21%) 11303M (69%)", + "[2024-11-19T09:48:52.821-0600][info ][gc,heap ] GC(4) y: Reclaimed: - - 420M (3%) 9073M (55%)", + "[2024-11-19T09:48:52.821-0600][info ][gc,heap ] GC(4) y: Promoted: - - 105M (1%) 201M (1%)", + "[2024-11-19T09:48:52.821-0600][info ][gc,heap ] GC(4) y: Compacted: - - - 2352M (14%)", + "[2024-11-19T09:48:52.821-0600][info ][gc,phases ] GC(4) y: Young Generation 13310M(81%)->15654M(96%) 4.926s", + "[2024-11-19T09:48:52.821-0600][info ][gc ] GC(4) Minor Collection (Allocation Stall) 13310M(81%)->15734M(96%) 4.938s", + "[2024-11-19T09:48:52.821-0600][info ][gc,task ] GC(3) O: Using 3 Workers for Old Generation", + "[2024-11-19T09:48:52.853-0600][info ][gc,task ] GC(3) O: Using 1 Workers for Old Generation", + "[2024-11-19T09:48:52.855-0600][info ][gc,phases ] GC(3) O: Concurrent Remap Roots 33.641ms", + "[2024-11-19T09:48:52.855-0600][info ][gc,phases ] GC(3) O: Pause Relocate Start 0.006ms", + "[2024-11-19T09:48:52.855-0600][info ][gc ] GC(5) Minor Collection (Allocation Rate)", + "[2024-11-19T09:48:52.855-0600][info ][gc,task ] GC(5) Using 3 Workers for Young Generation", + "[2024-11-19T09:48:52.855-0600][info ][gc,phases ] GC(5) y: Young Generation", + "[2024-11-19T09:48:52.860-0600][info ][gc,phases ] GC(5) y: Pause Mark Start 0.004ms", + "[2024-11-19T09:48:52.868-0600][info ][gc,phases ] GC(3) O: Concurrent Relocate 12.604ms", + "[2024-11-19T09:48:55.559-0600][info ][gc,phases ] GC(5) y: Concurrent Mark 2695.516ms", + "[2024-11-19T09:48:55.559-0600][info ][gc,phases ] GC(5) y: Pause Mark End 0.013ms", + "[2024-11-19T09:48:55.559-0600][info ][gc,phases ] GC(5) y: Concurrent Mark Free 0.000ms", + "[2024-11-19T09:48:55.559-0600][info ][gc,phases ] GC(5) y: Concurrent Reset Relocation Set 0.377ms", + "[2024-11-19T09:48:55.561-0600][info ][gc,reloc ] GC(5) y: Using tenuring threshold: 2 (Computed)", + "[2024-11-19T09:48:55.828-0600][info ][gc,phases ] GC(5) y: Concurrent Select Relocation Set 268.261ms", + "[2024-11-19T09:48:55.830-0600][info ][gc,phases ] GC(5) y: Pause Relocate Start 0.005ms", + "[2024-11-19T09:48:57.412-0600][info ][gc,phases ] GC(5) y: Concurrent Relocate 1581.464ms", + "[2024-11-19T09:48:57.415-0600][info ][gc,alloc ] GC(5) y: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:57.415-0600][info ][gc,alloc ] GC(5) y: Allocation Stalls: 0 65 33 0", + "[2024-11-19T09:48:57.415-0600][info ][gc,load ] GC(5) y: Load: 25.07 (209%) / 9.29 (77%) / 5.42 (45%)", + "[2024-11-19T09:48:57.415-0600][info ][gc,mmu ] GC(5) y: MMU: 2ms/98.8%, 5ms/99.5%, 10ms/99.8%, 20ms/99.9%, 50ms/99.9%, 100ms/100.0%", + "[2024-11-19T09:48:57.415-0600][info ][gc,marking ] GC(5) y: Mark: 2 stripe(s), 10 proactive flush(es), 1 terminate flush(es), 0 completion(s), 0 continuation(s)", + "[2024-11-19T09:48:57.415-0600][info ][gc,marking ] GC(5) y: Mark Stack Usage: 32M", + "[2024-11-19T09:48:57.415-0600][info ][gc,nmethod ] GC(5) y: NMethods: 5407 registered, 0 unregistered", + "[2024-11-19T09:48:57.415-0600][info ][gc,metaspace] GC(5) y: Metaspace: 46M used, 46M committed, 1088M reserved", + "[2024-11-19T09:48:57.415-0600][info ][gc,reloc ] GC(5) y: Candidates Selected In-Place Size Empty Relocated", + "[2024-11-19T09:48:57.415-0600][info ][gc,reloc ] GC(5) y: Small Pages: 7818 4111 2 15636M 1020M 1285M", + "[2024-11-19T09:48:57.415-0600][info ][gc,reloc ] GC(5) y: Medium Pages: 0 0 0 0M 0M 0M", + "[2024-11-19T09:48:57.418-0600][info ][gc,reloc ] GC(5) y: Large Pages: 0 0 0 0M 0M 0M", + "[2024-11-19T09:48:57.418-0600][info ][gc,reloc ] GC(5) y: Forwarding Usage: 705M", + "[2024-11-19T09:48:57.418-0600][info ][gc,reloc ] GC(5) y: Age Table:", + "[2024-11-19T09:48:57.418-0600][info ][gc,reloc ] GC(5) y: Live Garbage Small Medium Large", + "[2024-11-19T09:48:57.418-0600][info ][gc,reloc ] GC(5) y: Eden 2017M (12%) 9514M (58%) 5766 / 4091 0 / 0 0 / 0", + "[2024-11-19T09:48:57.418-0600][info ][gc,reloc ] GC(5) y: Survivor 1 2356M (14%) 39M (0%) 1198 / 2 0 / 0 0 / 0", + "[2024-11-19T09:48:57.418-0600][info ][gc,reloc ] GC(5) y: Survivor 2 1477M (9%) 230M (1%) 854 / 18 0 / 0 0 / 0", + "[2024-11-19T09:48:57.418-0600][info ][gc,heap ] GC(5) y: Min Capacity: 8M(0%)", + "[2024-11-19T09:48:57.418-0600][info ][gc,heap ] GC(5) y: Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:57.418-0600][info ][gc,heap ] GC(5) y: Soft Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:57.419-0600][info ][gc,heap ] GC(5) y: Heap Statistics:", + "[2024-11-19T09:48:57.419-0600][info ][gc,heap ] GC(5) y: Mark Start Mark End Relocate Start Relocate End High Low", + "[2024-11-19T09:48:57.419-0600][info ][gc,heap ] GC(5) y: Capacity: 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%)", + "[2024-11-19T09:48:57.419-0600][info ][gc,heap ] GC(5) y: Free: 494M (3%) 0M (0%) 0M (0%) 3288M (20%) 6336M (39%) 0M (0%)", + "[2024-11-19T09:48:57.419-0600][info ][gc,heap ] GC(5) y: Used: 15890M (97%) 16384M (100%) 16384M (100%) 13096M (80%) 16384M (100%) 10048M (61%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Young Generation Statistics:", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Used: 15636M (95%) 16130M (98%) 14524M (89%) 11180M (68%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Live: - 5852M (36%) 4426M (27%) 4374M (27%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Garbage: - 9783M (60%) 8583M (52%) 47M (0%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Allocated: - 494M (3%) 1514M (9%) 6758M (41%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Reclaimed: - - 1200M (7%) 9736M (59%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Promoted: - - 1425M (9%) 1477M (9%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,heap ] GC(5) y: Compacted: - - - 1995M (12%)", + "[2024-11-19T09:48:57.422-0600][info ][gc,phases ] GC(5) y: Young Generation 15890M(97%)->13096M(80%) 4.560s", + "[2024-11-19T09:48:57.422-0600][info ][gc ] GC(5) Minor Collection (Allocation Rate) 15882M(97%)->13144M(80%) 4.567s", + "[2024-11-19T09:48:57.422-0600][info ][gc,alloc ] GC(3) O: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:57.423-0600][info ][gc,alloc ] GC(3) O: Allocation Stalls: 0 0 0 0", + "[2024-11-19T09:48:57.423-0600][info ][gc,load ] GC(3) O: Load: 25.07 (209%) / 9.29 (77%) / 5.42 (45%)", + "[2024-11-19T09:48:57.427-0600][info ][gc,mmu ] GC(3) O: MMU: 2ms/98.8%, 5ms/99.5%, 10ms/99.8%, 20ms/99.9%, 50ms/99.9%, 100ms/100.0%", + "[2024-11-19T09:48:57.427-0600][info ][gc,marking ] GC(3) O: Mark: 1 stripe(s), 1 proactive flush(es), 1 terminate flush(es), 0 completion(s), 0 continuation(s)", + "[2024-11-19T09:48:57.427-0600][info ][gc,marking ] GC(3) O: Mark Stack Usage: 0M", + "[2024-11-19T09:48:57.427-0600][info ][gc,nmethod ] GC(3) O: NMethods: 5407 registered, 0 unregistered", + "[2024-11-19T09:48:57.427-0600][info ][gc,metaspace] GC(3) O: Metaspace: 46M used, 46M committed, 1088M reserved", + "[2024-11-19T09:48:57.427-0600][info ][gc,ref ] GC(3) O: Encountered Discovered Enqueued", + "[2024-11-19T09:48:57.427-0600][info ][gc,ref ] GC(3) O: Soft References: 4553 0 0", + "[2024-11-19T09:48:57.427-0600][info ][gc,ref ] GC(3) O: Weak References: 11144 0 0", + "[2024-11-19T09:48:57.427-0600][info ][gc,ref ] GC(3) O: Final References: 936 0 0", + "[2024-11-19T09:48:57.427-0600][info ][gc,ref ] GC(3) O: Phantom References: 8720 0 0", + "[2024-11-19T09:48:57.427-0600][info ][gc,heap ] GC(3) O: Min Capacity: 8M(0%)", + "[2024-11-19T09:48:57.427-0600][info ][gc,heap ] GC(3) O: Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:57.427-0600][info ][gc,heap ] GC(3) O: Soft Max Capacity: 16384M(100%)", + "[2024-11-19T09:48:57.427-0600][info ][gc,heap ] GC(3) O: Heap Statistics:", + "[2024-11-19T09:48:57.427-0600][info ][gc,heap ] GC(3) O: Mark Start Mark End Relocate Start Relocate End High Low", + "[2024-11-19T09:48:57.427-0600][info ][gc,heap ] GC(3) O: Capacity: 8962M (55%) 16384M (100%) 16384M (100%) 16384M (100%) 16384M (100%) 8962M (55%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Free: 7422M (45%) 2516M (15%) 502M (3%) 484M (3%) 7422M (45%) 0M (0%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Used: 8962M (55%) 13868M (85%) 15882M (97%) 15900M (97%) 16384M (100%) 8962M (55%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Old Generation Statistics:", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Mark Start Mark End Relocate Start Relocate End", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Used: 0M (0%) 0M (0%) 254M (2%) 254M (2%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Live: - 0M (0%) 0M (0%) 0M (0%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Garbage: - 0M (0%) 0M (0%) 0M (0%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Allocated: - 0M (0%) 254M (2%) 254M (2%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Reclaimed: - - 0M (0%) 0M (0%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,heap ] GC(3) O: Compacted: - - - 0M (0%)", + "[2024-11-19T09:48:57.431-0600][info ][gc,phases ] GC(3) O: Old Generation 13310M(81%)->15900M(97%) 9.540s", + "[2024-11-19T09:48:57.431-0600][info ][gc ] GC(3) Major Collection (Warmup) 8960M(55%)->13184M(80%) 14.923s", + }; + List events = feedParser(eventLogEntries); + + assertEquals(4, events.size()); + + ZGCYoungCollection majorYoung = (ZGCYoungCollection) events.get(0); + assertEquals(3L, majorYoung.getGcId()); + assertEquals(GarbageCollectionTypes.ZGCMajorYoung, majorYoung.getGarbageCollectionType()); + + ZGCYoungCollection minorYoungA = (ZGCYoungCollection) events.get(1); + assertEquals(4L, minorYoungA.getGcId()); + assertEquals(GarbageCollectionTypes.ZGCMinorYoung, minorYoungA.getGarbageCollectionType()); + + ZGCYoungCollection minorYoungB = (ZGCYoungCollection) events.get(2); + assertEquals(5L, minorYoungB.getGcId()); + assertEquals(GarbageCollectionTypes.ZGCMinorYoung, minorYoungB.getGarbageCollectionType()); + + ZGCOldCollection majorOld = (ZGCOldCollection) events.get(3); + assertEquals(3L, majorOld.getGcId()); + assertEquals(GarbageCollectionTypes.ZGCMajorOld, majorOld.getGarbageCollectionType()); + + } + private boolean checkReferenceSummary(ZGCReferenceSummary refSummary, long encounderted, long discovered, long enqueued) { return refSummary.getEncountered() == encounderted && refSummary.getDiscovered() == discovered && refSummary.getEnqueued() == enqueued; } diff --git a/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserRulesTest.java b/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserRulesTest.java index f8b5947d..e4f83fee 100644 --- a/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserRulesTest.java +++ b/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserRulesTest.java @@ -83,7 +83,9 @@ private void evaluate(GCParseRule rule, String string, boolean dump) { MEMORY_TABLE_ENTRY_SIZE, MEMORY_TABLE_ENTRY_OCCUPANCY, MEMORY_TABLE_ENTRY_RECLAIMED_PROMOTED, - MEMORY_SUMMARY + MEMORY_SUMMARY, + GENERATION_START, // 15 + END_OF_PHASE_SUMMARY_GEN, }; private String[][] lines = { @@ -148,6 +150,19 @@ private void evaluate(GCParseRule rule, String string, boolean dump) { }, { // 14 "[32.193s][info][gc ] GC(2) Garbage Collection (Metadata GC Threshold) 558M(2%)->126M(0%)", + }, + { // 15 + "[2024-11-19T09:48:57.431-0600][info ][gc,phases ] GC(6) Y: Young Generation (Promote All)", + "[2024-11-19T09:48:42.508-0600][info ][gc,phases ] GC(3) Y: Young Generation", + "[2024-11-19T09:48:31.984-0600][info][gc,phases ] GC(0) O: Old Generation", + "[2024-11-19T09:48:52.855-0600][info ][gc,phases ] GC(5) y: Young Generation" + }, + { // 16 + "[2024-11-19T09:48:31.984-0600][info][gc,phases ] GC(0) Y: Young Generation 88M(1%)->54M(0%) 0.017s", + "[2024-11-19T09:49:02.950-0600][info ][gc,phases ] GC(6) Y: Young Generation (Promote All) 13184M(80%)->16384M(100%) 5.519s", + "[2024-11-19T09:48:31.997-0600][info][gc,phases ] GC(0) O: Old Generation 54M(0%)->56M(0%) 0.013s", + "[2024-11-19T09:48:52.821-0600][info ][gc,phases ] GC(4) y: Young Generation 13310M(81%)->15654M(96%) 4.926s", + "[2025-02-11T13:07:13.256-0800][info][gc,phases ] GC(7) y: Young Generation 14720M(40%)->2054M(6%) 0.689s", } }; diff --git a/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java b/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java index 6b2735ca..98c8cca6 100644 --- a/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java +++ b/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java @@ -3,14 +3,7 @@ package com.microsoft.gctoolkit.parser; import com.microsoft.gctoolkit.event.jvm.JVMEvent; -import com.microsoft.gctoolkit.event.zgc.FullZGCCycle; -import com.microsoft.gctoolkit.event.zgc.ZGCAllocatedSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCGarbageSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCLiveSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCMemoryPoolSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCMemorySummary; -import com.microsoft.gctoolkit.event.zgc.ZGCMetaspaceSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCReclaimSummary; +import com.microsoft.gctoolkit.event.zgc.*; import com.microsoft.gctoolkit.jvm.Diarizer; import com.microsoft.gctoolkit.parser.jvm.UnifiedDiarizer; import org.junit.jupiter.api.Test; @@ -75,7 +68,7 @@ public void infoLevelZGCCycle() { List singleCycle = feedParser(eventLogEntries); try { assertEquals(1, singleCycle.size()); - FullZGCCycle zgc = (FullZGCCycle) singleCycle.get(0); + ZGCFullCollection zgc = (ZGCFullCollection) singleCycle.get(0); assertEquals(zgc.getGcId(), 2L); diff --git a/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/CollectionCycleCountsAggregator.java b/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/CollectionCycleCountsAggregator.java index 6f7eedaf..5bfa645d 100644 --- a/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/CollectionCycleCountsAggregator.java +++ b/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/CollectionCycleCountsAggregator.java @@ -7,9 +7,9 @@ import com.microsoft.gctoolkit.event.g1gc.G1GCPauseEvent; import com.microsoft.gctoolkit.event.generational.GenerationalGCPauseEvent; import com.microsoft.gctoolkit.event.shenandoah.ShenandoahCycle; -import com.microsoft.gctoolkit.event.zgc.FullZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MajorZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MinorZGCCycle; +import com.microsoft.gctoolkit.event.zgc.ZGCFullCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCOldCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCYoungCollection; @Aggregates({EventSource.G1GC,EventSource.GENERATIONAL,EventSource.ZGC,EventSource.SHENANDOAH}) public class CollectionCycleCountsAggregator extends Aggregator { @@ -19,21 +19,21 @@ public CollectionCycleCountsAggregator(CollectionCycleCountsAggregation results) register(GenerationalGCPauseEvent.class, this::count); register(G1GCPauseEvent.class, this::count); register(G1GCConcurrentEvent.class, this::count); - register(FullZGCCycle.class,this::count); - register(MajorZGCCycle.class,this::count); - register(MinorZGCCycle.class,this::count); + register(ZGCFullCollection.class, this::count); + register(ZGCOldCollection.class, this::count); + register(ZGCYoungCollection.class, this::count); register(ShenandoahCycle.class,this::count); } - private void count(MinorZGCCycle event) { + private void count(ZGCYoungCollection event) { aggregation().count(event.getGarbageCollectionType()); } - private void count(MajorZGCCycle event) { + private void count(ZGCOldCollection event) { aggregation().count(event.getGarbageCollectionType()); } - private void count(FullZGCCycle event) { + private void count(ZGCFullCollection event) { aggregation().count(event.getGarbageCollectionType()); } diff --git a/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/HeapOccupancyAfterCollection.java b/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/HeapOccupancyAfterCollection.java index ac787e96..c1c800c5 100644 --- a/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/HeapOccupancyAfterCollection.java +++ b/sample/src/main/java/com/microsoft/gctoolkit/sample/aggregation/HeapOccupancyAfterCollection.java @@ -6,9 +6,9 @@ import com.microsoft.gctoolkit.event.g1gc.G1GCPauseEvent; import com.microsoft.gctoolkit.event.generational.GenerationalGCPauseEvent; import com.microsoft.gctoolkit.event.shenandoah.ShenandoahCycle; -import com.microsoft.gctoolkit.event.zgc.FullZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MajorZGCCycle; -import com.microsoft.gctoolkit.event.zgc.MinorZGCCycle; +import com.microsoft.gctoolkit.event.zgc.ZGCFullCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCOldCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCYoungCollection; @Aggregates({EventSource.G1GC,EventSource.GENERATIONAL,EventSource.ZGC,EventSource.SHENANDOAH}) public class HeapOccupancyAfterCollection extends Aggregator { @@ -17,17 +17,17 @@ public HeapOccupancyAfterCollection(HeapOccupancyAfterCollectionAggregation resu super(results); register(GenerationalGCPauseEvent.class, this::extractHeapOccupancy); register(G1GCPauseEvent.class, this::extractHeapOccupancy); - register(FullZGCCycle.class,this::extractHeapOccupancy); - register(MajorZGCCycle.class,this::extractHeapOccupancy); - register(MinorZGCCycle.class,this::extractHeapOccupancy); + register(ZGCFullCollection.class, this::extractHeapOccupancy); + register(ZGCOldCollection.class, this::extractHeapOccupancy); + register(ZGCYoungCollection.class, this::extractHeapOccupancy); register(ShenandoahCycle.class,this::extractHeapOccupancy); } - private void extractHeapOccupancy(MinorZGCCycle event) { + private void extractHeapOccupancy(ZGCYoungCollection event) { aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getMemorySummary().getOccupancyAfter()); } - private void extractHeapOccupancy(MajorZGCCycle event) { + private void extractHeapOccupancy(ZGCOldCollection event) { aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getMemorySummary().getOccupancyAfter()); } @@ -40,7 +40,7 @@ private void extractHeapOccupancy(G1GCPauseEvent event) { } - private void extractHeapOccupancy(FullZGCCycle event) { + private void extractHeapOccupancy(ZGCFullCollection event) { aggregation().addDataPoint(event.getGarbageCollectionType(), event.getDateTimeStamp(), event.getMemorySummary().getOccupancyAfter()); } From b206adea48bdce5869b02971d4b7d7546e87ce72 Mon Sep 17 00:00:00 2001 From: Anthony Kiselev Date: Wed, 11 Jun 2025 12:49:08 -0500 Subject: [PATCH 2/5] Fix mismatched GC type label --- .../com/microsoft/gctoolkit/event/GarbageCollectionTypes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java b/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java index e6af2e1a..4f184d49 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java +++ b/api/src/main/java/com/microsoft/gctoolkit/event/GarbageCollectionTypes.java @@ -57,7 +57,7 @@ public enum GarbageCollectionTypes implements LabelledGCEventType { Unknown("Unknown"), ZGCFull("ZGC FULL"), ZGCMajorOld("ZGC Major Old"), - ZGCMajorYoung("ZGC Major Old"), + ZGCMajorYoung("ZGC Major Young"), ZGCMinorYoung("ZGC Minor Young"), Shenandoah("Shenandoah"); From a89f4ef02885068b8cef99424037ece5fb345457 Mon Sep 17 00:00:00 2001 From: Anthony Kiselev Date: Mon, 16 Jun 2025 13:48:14 -0500 Subject: [PATCH 3/5] Rename ZGCCollectionType -> ZGCCycleType --- .../gctoolkit/event/zgc/ZGCCollection.java | 6 ++--- ...CCollectionType.java => ZGCCycleType.java} | 22 +++++++++---------- .../gctoolkit/parser/GCLogTrace.java | 3 --- .../microsoft/gctoolkit/parser/ZGCParser.java | 12 +++++----- 4 files changed, 20 insertions(+), 23 deletions(-) rename api/src/main/java/com/microsoft/gctoolkit/event/zgc/{ZGCCollectionType.java => ZGCCycleType.java} (53%) diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollection.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollection.java index 6ec65d8d..e14e959b 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollection.java +++ b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollection.java @@ -21,7 +21,7 @@ public class ZGCCollection extends GCEvent { private ZGCMarkSummary markSummary; private ZGCPromotedSummary promotedSummary; private ZGCCompactedSummary compactedSummary; - private ZGCCollectionType type; + private ZGCCycleType type; private ZGCPhase phase; private OccupancySummary generationUsedSummary; private long gcId; @@ -425,11 +425,11 @@ public OccupancySummary getGenerationUsedSummary() { return generationUsedSummary; } - public ZGCCollectionType getType() { + public ZGCCycleType getType() { return type; } - public void setType(ZGCCollectionType type) { + public void setType(ZGCCycleType type) { this.type = type; } diff --git a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollectionType.java b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCycleType.java similarity index 53% rename from api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollectionType.java rename to api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCycleType.java index 5292d4eb..945e8d6a 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCollectionType.java +++ b/api/src/main/java/com/microsoft/gctoolkit/event/zgc/ZGCCycleType.java @@ -3,31 +3,31 @@ import java.util.Arrays; import java.util.Objects; -public enum ZGCCollectionType { +public enum ZGCCycleType { FULL("Garbage"), // Legacy ZGC MINOR("Minor"), MAJOR("Major"); - private final String collectionLabel; + private final String cycleLabel; - ZGCCollectionType(String collectionLabel) { - this.collectionLabel = collectionLabel; + ZGCCycleType(String cycleLabel) { + this.cycleLabel = cycleLabel; } - public static ZGCCollectionType get(String label) { - return Arrays.stream(ZGCCollectionType.class.getEnumConstants()) - .filter(collectionType -> Objects.equals(collectionType.collectionLabel, label)) + public static ZGCCycleType get(String label) { + return Arrays.stream(ZGCCycleType.class.getEnumConstants()) + .filter(collectionType -> Objects.equals(collectionType.cycleLabel, label)) .findFirst() .orElse(null); } - public static ZGCCollectionType fromPhase(ZGCPhase phase){ + public static ZGCCycleType fromPhase(ZGCPhase phase){ if(phase == ZGCPhase.FULL){ - return ZGCCollectionType.FULL; + return ZGCCycleType.FULL; } else if (phase == ZGCPhase.MAJOR_YOUNG || phase == ZGCPhase.MAJOR_OLD){ - return ZGCCollectionType.MAJOR; + return ZGCCycleType.MAJOR; } else if (phase == ZGCPhase.MINOR_YOUNG){ - return ZGCCollectionType.MINOR; + return ZGCCycleType.MINOR; } else { throw new IllegalArgumentException(String.format("Unknown ZGCPhase: %s", phase)); } diff --git a/parser/src/main/java/com/microsoft/gctoolkit/parser/GCLogTrace.java b/parser/src/main/java/com/microsoft/gctoolkit/parser/GCLogTrace.java index 9607d284..40f210f2 100644 --- a/parser/src/main/java/com/microsoft/gctoolkit/parser/GCLogTrace.java +++ b/parser/src/main/java/com/microsoft/gctoolkit/parser/GCLogTrace.java @@ -11,15 +11,12 @@ import com.microsoft.gctoolkit.event.UnifiedStatisticalSummary; import com.microsoft.gctoolkit.event.jvm.MetaspaceRecord; import com.microsoft.gctoolkit.event.jvm.PermGenSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCCollectionType; import com.microsoft.gctoolkit.event.zgc.ZGCPhase; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; -import static com.microsoft.gctoolkit.event.zgc.ZGCPhase.FULL; - /** * Class that represents a chunk of GC log that we are attempting to match to a * known GC log pattern diff --git a/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java b/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java index dd72d93f..2083157f 100644 --- a/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java +++ b/parser/src/main/java/com/microsoft/gctoolkit/parser/ZGCParser.java @@ -24,7 +24,7 @@ import com.microsoft.gctoolkit.event.zgc.ZGCPhase; import com.microsoft.gctoolkit.event.zgc.ZGCPromotedSummary; import com.microsoft.gctoolkit.event.zgc.ZGCReclaimSummary; -import com.microsoft.gctoolkit.event.zgc.ZGCCollectionType; +import com.microsoft.gctoolkit.event.zgc.ZGCCycleType; import com.microsoft.gctoolkit.event.zgc.ZGCCollection; import com.microsoft.gctoolkit.event.zgc.ZGCMarkSummary; import com.microsoft.gctoolkit.event.zgc.ZGCMemoryPoolSummary; @@ -193,8 +193,8 @@ private void setForwardRefForPhase(ZGCPhase zgcPhase, ZGCForwardReference forwar } private void cycleStart(GCLogTrace trace, String s) { - ZGCCollectionType type = ZGCCollectionType.get(trace.getGroup(2)); - if(type == ZGCCollectionType.FULL){ + ZGCCycleType type = ZGCCycleType.get(trace.getGroup(2)); + if(type == ZGCCycleType.FULL){ setForwardRefForPhase( ZGCPhase.FULL, new ZGCForwardReference(getClock(), trace.getLongGroup(1), trace.gcCause(3,0), type, ZGCPhase.FULL) @@ -215,7 +215,7 @@ private void generationStart(GCLogTrace trace, String line){ ZGCPhase phase = ZGCPhase.get(trace.getGroup(2)); long gcId = trace.getLongGroup(1); GCCause gcCause = gcCauseMap.getOrDefault(gcId, GCCause.UNKNOWN_GCCAUSE); - ZGCForwardReference forwardReference = new ZGCForwardReference(getClock(), gcId, gcCause, ZGCCollectionType.fromPhase(phase), phase); + ZGCForwardReference forwardReference = new ZGCForwardReference(getClock(), gcId, gcCause, ZGCCycleType.fromPhase(phase), phase); setForwardRefForPhase( phase, forwardReference @@ -622,7 +622,7 @@ public ZGCMemoryPoolSummary buildRelocateEnd(){ private static class ZGCForwardReference { private final DateTimeStamp startTimeStamp; private final GCCause gcCause; - private final ZGCCollectionType type; + private final ZGCCycleType type; private final ZGCPhase phase; private final long gcId; @@ -695,7 +695,7 @@ private static class ZGCForwardReference { private List ageTableSummary; private final ZGCMemoryPoolSummaryBuilder memoryPoolSummaryBuilder; - public ZGCForwardReference(DateTimeStamp dateTimeStamp, long gcId, GCCause cause, ZGCCollectionType type, ZGCPhase phase) { + public ZGCForwardReference(DateTimeStamp dateTimeStamp, long gcId, GCCause cause, ZGCCycleType type, ZGCPhase phase) { this.startTimeStamp = dateTimeStamp; this.gcId = gcId; this.gcCause = cause; From fb58a04c0ad98d62f0f859814d0bb09bd95f31a4 Mon Sep 17 00:00:00 2001 From: Anthony Kiselev Date: Mon, 16 Jun 2025 13:48:53 -0500 Subject: [PATCH 4/5] Fix inconsistent whitespace --- .../main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java b/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java index 0ca78ce5..f58b71c2 100644 --- a/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java +++ b/api/src/main/java/com/microsoft/gctoolkit/jvm/SupportedFlags.java @@ -37,7 +37,7 @@ public enum SupportedFlags { PRINT_PROMOTION_FAILURE, // 26 PRINT_FLS_STATISTICS, // 27 - PRINT_CPU_TIMES, // 28 + PRINT_CPU_TIMES, // 28 GENERATIONAL_ZGC, // 29 From 96bbb9aebd393e8d83206ea0e4ffe5455a22b3d6 Mon Sep 17 00:00:00 2001 From: Anthony Kiselev Date: Tue, 17 Jun 2025 08:41:06 -0500 Subject: [PATCH 5/5] Use explicit imports in ZGCParserTest --- .../com/microsoft/gctoolkit/parser/ZGCParserTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java b/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java index 98c8cca6..ab8be0eb 100644 --- a/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java +++ b/parser/src/test/java/com/microsoft/gctoolkit/parser/ZGCParserTest.java @@ -3,7 +3,14 @@ package com.microsoft.gctoolkit.parser; import com.microsoft.gctoolkit.event.jvm.JVMEvent; -import com.microsoft.gctoolkit.event.zgc.*; +import com.microsoft.gctoolkit.event.zgc.ZGCAllocatedSummary; +import com.microsoft.gctoolkit.event.zgc.ZGCFullCollection; +import com.microsoft.gctoolkit.event.zgc.ZGCGarbageSummary; +import com.microsoft.gctoolkit.event.zgc.ZGCLiveSummary; +import com.microsoft.gctoolkit.event.zgc.ZGCMemoryPoolSummary; +import com.microsoft.gctoolkit.event.zgc.ZGCMemorySummary; +import com.microsoft.gctoolkit.event.zgc.ZGCMetaspaceSummary; +import com.microsoft.gctoolkit.event.zgc.ZGCReclaimSummary; import com.microsoft.gctoolkit.jvm.Diarizer; import com.microsoft.gctoolkit.parser.jvm.UnifiedDiarizer; import org.junit.jupiter.api.Test;