Skip to content
Merged

424 #432

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
416eb87
bug: intermediate commit to allow work on another bug
kcpeppe Jan 8, 2024
d7ab6fb
bug: add more robust handling of IllegalArgumentException in GCToolKi…
kcpeppe Jan 24, 2024
cfccf95
Merge branch 'filter'
kcpeppe Jan 24, 2024
3725095
tidy: remove debug to stdout to logging framework
kcpeppe Jan 25, 2024
f7efb6e
refactor: Ensure DateTimeStamp cannot be malformed and it behaves if …
kcpeppe Feb 22, 2024
15a86b9
Merge branch 'main' of github.com:microsoft/gctoolkit into 316
kcpeppe Feb 22, 2024
9fa0e34
refactor: update pom for new GC log test data bundle
kcpeppe Feb 22, 2024
1e9f897
tidy: address comments from PR
kcpeppe Feb 23, 2024
59dc331
Update parser/src/main/java/com/microsoft/gctoolkit/parser/GCLogParse…
karianna Feb 23, 2024
bed6ae6
feature: first push to combine CMS parser with GenerationalHeapParser
kcpeppe Feb 27, 2024
278b7ac
depreciate: depreciated the CMS preunified event source
kcpeppe Feb 27, 2024
8012bd0
refactor: get all tests to pass
kcpeppe Mar 1, 2024
86e2578
refactor: continue to get tests to pass
kcpeppe Mar 1, 2024
82e8f4f
refactor: continue to get tests to pass
kcpeppe Mar 1, 2024
115996b
refactor: collapse CMS phases parser into generational parser
kcpeppe Mar 11, 2024
d0dbcbd
refactor: fix merge conflicts
kcpeppe Mar 11, 2024
9de145d
Merge branch '318'
kcpeppe Mar 11, 2024
7e52270
Merge branch 'main' of github.com:kcpeppe/gctoolkit
kcpeppe Mar 11, 2024
e21cb1c
refactor: GenerationalHeapParser was duplicating CMF failures under c…
kcpeppe Mar 14, 2024
40595f0
refactor: ensure GC log is closed when discovering the format
kcpeppe Mar 14, 2024
cd7f1a2
refactor: add test for reported bug
kcpeppe Mar 15, 2024
7a8e8f7
refactor: add ability to parse very simple logs preunified logs
kcpeppe Mar 26, 2024
82a775a
refactor: fix merge conflict that wasn't an actual merge conflict :-\
kcpeppe Mar 26, 2024
ac853e7
refactor: remove no longer needed print statement
kcpeppe Mar 26, 2024
39afac3
refactor: tidy from review
kcpeppe Mar 26, 2024
12a17da
refactor: support date stamps only for preunified logs
kcpeppe Apr 11, 2024
a2062c4
merge: complete a strange merge
kcpeppe Apr 11, 2024
66e3466
refactor: bump version of gctoolkit testdata to support new tests
kcpeppe Apr 11, 2024
fcb4ebd
refactor: small code cleanups
kcpeppe Apr 11, 2024
a90ec25
Update parser/src/main/java/com/microsoft/gctoolkit/parser/AbstractLo…
kcpeppe Apr 16, 2024
3e41273
tidy: cleanup from review and added more tests
kcpeppe Apr 18, 2024
7e60928
tidy: resolved merge conflict
kcpeppe Apr 18, 2024
3c015e6
Merge branch 'main' of github.com:microsoft/gctoolkit
kcpeppe Apr 23, 2024
02000b2
Merge branch 'main' of github.com:microsoft/gctoolkit
kcpeppe Dec 19, 2024
19e655a
refactor: adjust unified generational GC log parser to produce System…
kcpeppe Dec 19, 2024
0493c30
refactor: update source data to include new serial GC log file
kcpeppe Dec 22, 2024
309cc21
refactor: prep for merge with upstream/main
kcpeppe Mar 20, 2025
de5e146
tidy: fixup merge conflict
kcpeppe Mar 20, 2025
b23baa2
refactor: add survivor record to the G1Young events
kcpeppe Apr 11, 2025
882c86d
refactor: adding in tenuring record
kcpeppe Apr 14, 2025
3607db3
Merge branch 'main' of github.com:microsoft/gctoolkit into 424
kcpeppe Apr 15, 2025
96e4db1
refactor: update testdata version #
kcpeppe Apr 21, 2025
12e7e2b
refactor: add in tests for Survivor records found in GCEvent
kcpeppe Apr 22, 2025
1b36a1e
refactor: update test data
kcpeppe Apr 22, 2025
bd2f366
fix highly unlikely AIOBE
Apr 22, 2025
ef88999
do not range check age arg in SurvivorRecord
Apr 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions api/src/main/java/com/microsoft/gctoolkit/event/g1gc/G1Young.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.microsoft.gctoolkit.event.GarbageCollectionTypes;
import com.microsoft.gctoolkit.event.StatisticalSummary;
import com.microsoft.gctoolkit.event.UnifiedStatisticalSummary;
import com.microsoft.gctoolkit.event.jvm.SurvivorRecord;
import com.microsoft.gctoolkit.time.DateTimeStamp;

import java.util.Iterator;
Expand Down Expand Up @@ -36,6 +37,7 @@ public class G1Young extends G1RealPause {
private StatisticalSummary workerTotal;
private StatisticalSummary processedBuffersSummary;
private boolean toSpaceExhausted = false;
private SurvivorRecord survivorRecord;

private final Map<String, StatisticalSummary> parallelPhaseSummaries = new ConcurrentHashMap<>();
private final Map<String, Double> phaseDurations = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -196,6 +198,14 @@ public void addWorkerActivity(String group, StatisticalSummary statisticalSummar
workerTotal = statisticalSummary;
}

public void add(SurvivorRecord record) {
this.survivorRecord = record;
}

public SurvivorRecord getSurvivorRecord() {
return survivorRecord;
}

public StatisticalSummary getWorkerOther() {
return this.workerOther;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.microsoft.gctoolkit.event.GarbageCollectionTypes;
import com.microsoft.gctoolkit.event.MemoryPoolSummary;
import com.microsoft.gctoolkit.event.ReferenceGCSummary;
import com.microsoft.gctoolkit.event.jvm.SurvivorRecord;
import com.microsoft.gctoolkit.time.DateTimeStamp;

public abstract class GenerationalGCPauseEvent extends GenerationalGCEvent {
Expand All @@ -23,6 +24,7 @@ public abstract class GenerationalGCPauseEvent extends GenerationalGCEvent {
private double stringTableProcessingTime;
private double symbolAndStringTableProcessingTime;
private BinaryTreeDictionary binaryTreeDictionary;
private SurvivorRecord survivorRecord;

private CPUSummary cpuSummary;

Expand Down Expand Up @@ -114,6 +116,14 @@ public void addClassUnloadingAndStringTableProcessingDurations(double classUnloa
this.symbolAndStringTableProcessingTime = symbolAndStringTable;
}

public void add(SurvivorRecord record) {
this.survivorRecord = record;
}

public SurvivorRecord getSurvivorRecord() {
return survivorRecord;
}

public double getClassUnloadingProcessingTime() {
return this.classUnloadingProcessingTime;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public class SurvivorRecord extends JVMEvent {
private int maxTenuringThreshold;

// JDK bug, we have now seen a max tenuring threshold of 32, even 64
// Fold anything older than 15 back into the 15th slot
private ArrayList<Long> bytesAtAge = null;
// Fold anything older than maxTenuringThreshold back into the maxTenuringThreshold slot
private long[] bytesAtAge;

public SurvivorRecord(DateTimeStamp timeStamp, long desiredOccupancy, int calculatedTenuringThreshold, int maxTenuringThreshold) {
super(timeStamp, 0.0d);
Expand Down Expand Up @@ -56,31 +56,30 @@ public int getMaxTenuringThreshold() {

public long getBytesAtAge(int age) {
if (this.bytesAtAge == null) return 0L;
return this.bytesAtAge.get(age);
return this.bytesAtAge[age];
}

/*
* There is a bug in the JVM that allows tenuring threshold to appear to be greater than 15.
* Fold anything greater than 15 into 15.
*
* Fold anything greater than maxTenuringThreshold into maxTenuringThreshold.
*/
public void add(int age, long bytes) {

if (bytesAtAge == null) {
bytesAtAge = new ArrayList<>();
bytesAtAge.add(0L); //throw away the first slow.
bytesAtAge = new long[maxTenuringThreshold+1];
bytesAtAge[0] = 0L; //throw away the first slot.
}

if (age <= maxTenuringThreshold) {
bytesAtAge.add(bytes);
bytesAtAge[age] = bytes;
} else {
bytesAtAge.set(maxTenuringThreshold, bytesAtAge.get(maxTenuringThreshold) + bytes);
bytesAtAge[maxTenuringThreshold] += bytes;
}
}

public Long[] getBytesAtEachAge() {
public long[] getBytesAtEachAge() {
if (bytesAtAge == null)
return new Long[0];
return bytesAtAge.toArray(new Long[0]);
return new long[0];
return bytesAtAge;
}
}
2 changes: 1 addition & 1 deletion gclogs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<packaging>pom</packaging>

<properties>
<gctoolkit-testdata-version>1.0.10</gctoolkit-testdata-version>
<gctoolkit-testdata-version>1.0.12</gctoolkit-testdata-version>
</properties>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.microsoft.gctoolkit.event.CPUSummary;
import com.microsoft.gctoolkit.event.GCCause;
import com.microsoft.gctoolkit.event.jvm.SurvivorRecord;
import com.microsoft.gctoolkit.parser.jvm.Decorators;
import com.microsoft.gctoolkit.time.DateTimeStamp;

Expand All @@ -15,6 +16,7 @@ public class ForwardReference {
private double duration = -1.0d;
private GCCause gcCause = GCCause.UNKNOWN_GCCAUSE;
private CPUSummary cpuSummary = null;
SurvivorRecord survivorRecord = null;

ForwardReference(Decorators decorators, int id) {
this.gcID = id;
Expand Down Expand Up @@ -69,4 +71,17 @@ Decorators getDecorators() {
return decorators;
}

public void survivorRecord(SurvivorRecord survivorRecord) {
this.survivorRecord = survivorRecord;
}

public void addAgeBreakout(int age, long volume) {
if (this.survivorRecord == null)
return;
this.survivorRecord.add(age, volume);
}

public SurvivorRecord getSurvivorRecord() {
return this.survivorRecord;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,8 @@ private G1Young buildYoung(G1Young collection) {
if (toSpaceExhausted) collection.toSpaceExhausted();
if (hasReferenceGCSummary())
collection.add(generateReferenceGCSummary());
if (survivorRecord != null)
collection.add(survivorRecord);
collection.addCPUSummary(getCPUSummary());
return collection;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.microsoft.gctoolkit.event.g1gc.G1GCPauseEvent;
import com.microsoft.gctoolkit.event.jvm.JVMEvent;
import com.microsoft.gctoolkit.event.jvm.JVMTermination;
import com.microsoft.gctoolkit.event.jvm.SurvivorRecord;
import com.microsoft.gctoolkit.jvm.Diary;
import com.microsoft.gctoolkit.message.ChannelName;
import com.microsoft.gctoolkit.message.JVMEventChannel;
Expand Down Expand Up @@ -47,7 +48,7 @@
* - pause time if it is reported or can be calculated
* todo: me
*/
public class UnifiedG1GCParser extends UnifiedGCLogParser implements UnifiedG1GCPatterns {
public class UnifiedG1GCParser extends UnifiedGCLogParser implements UnifiedG1GCPatterns, TenuredPatterns {

private static final Logger LOGGER = Logger.getLogger(UnifiedG1GCParser.class.getName());

Expand Down Expand Up @@ -154,6 +155,8 @@ public class UnifiedG1GCParser extends UnifiedGCLogParser implements UnifiedG1GC
parseRules.put(REBUILD_FREELIST, this::noop);
parseRules.put(NEW_CSET, this::noop);
parseRules.put(RESIZE_TLAB, this::noop);
parseRules.put(TENURING_SUMMARY, this::tenuringSummary);
parseRules.put(TENURING_AGE_BREAKDOWN, this::tenuringAgeBreakout);
}

public UnifiedG1GCParser() {
Expand Down Expand Up @@ -672,6 +675,25 @@ private void fullStringSymbolTable(GCLogTrace trace, String line) {
// forwardReference.scrubStringSymbolTableDuration(trace.getMillisecondDurationInSeconds());
}

/**
* Capture logged tenuring summary data
* @param trace
* @param line
*/
private void tenuringSummary(GCLogTrace trace, String line) {
forwardReference.survivorRecord(new SurvivorRecord(getClock(), trace.getLongGroup(1), trace.getIntegerGroup(2), trace.getIntegerGroup(3)));
}

/**
* Capture logged age table data
* @param trace
* @param line
*/
private void tenuringAgeBreakout(GCLogTrace trace, String line) {
notYetImplemented(trace,line);
forwardReference.addAgeBreakout(trace.getIntegerGroup(1), trace.getLongGroup(2));
}

/**
* records a concurrent phase of a concurrent cycle. After the event has been recorded, all other events
* that occurred during the concurrent event will be recorded.
Expand Down Expand Up @@ -726,8 +748,6 @@ private void jvmExit(GCLogTrace trace, String s) {
}

private boolean ignoreFrequentlySeenButUnwantedLines(String line) {
if (line.contains("Desired survivor size")) return true;
if (line.contains("Age table with threshold")) return true;
if (line.contains("safepoint")) return true;
if (line.contains(") Skipped phase ")) return true;
if (line.contains(" Total Min: ")) return true;
Expand All @@ -738,7 +758,7 @@ private boolean ignoreFrequentlySeenButUnwantedLines(String line) {
if (line.contains(" StringTable Weak Min:")) return true;
if (line.contains(" ResolvedMethodTable Weak Min:")) return true;
if (line.contains(" JNI Weak Min:")) return true;
return line.contains(" - age ");
return false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.microsoft.gctoolkit.event.generational.SystemGC;
import com.microsoft.gctoolkit.event.generational.YoungGC;
import com.microsoft.gctoolkit.event.jvm.JVMTermination;
import com.microsoft.gctoolkit.event.jvm.SurvivorRecord;
import com.microsoft.gctoolkit.jvm.Diary;
import com.microsoft.gctoolkit.message.ChannelName;
import com.microsoft.gctoolkit.message.JVMEventChannel;
Expand Down Expand Up @@ -63,7 +64,7 @@
* - from, to, configured
* - pause time if it is reported or can be calculated
*/
public class UnifiedGenerationalParser extends UnifiedGCLogParser implements UnifiedGenerationalPatterns {
public class UnifiedGenerationalParser extends UnifiedGCLogParser implements UnifiedGenerationalPatterns, TenuredPatterns {

private static final Logger LOGGER = Logger.getLogger(UnifiedGenerationalParser.class.getName());

Expand Down Expand Up @@ -100,6 +101,8 @@ public class UnifiedGenerationalParser extends UnifiedGCLogParser implements Uni
parseRules.put(JVM_EXIT, this::jvmExit);
parseRules.put(END_OF_FILE, this::jvmExit);
parseRules.put(METASPACE_DETAILED, this::metaSpaceDetails);
parseRules.put(TENURING_SUMMARY, this::tenuringSummary);
parseRules.put(TENURING_AGE_BREAKDOWN, this::tenuringAgeBreakout);

}

Expand Down Expand Up @@ -229,6 +232,26 @@ private void youngDetails(GCLogTrace trace, String line) {
pauseEvent.setHeap(trace.getOccupancyBeforeAfterWithMemoryPoolSizeSummary(2));
}

/**
* Capture logged tenuring summary data
* @param trace
* @param line
*/
private void tenuringSummary(GCLogTrace trace, String line) {
if ( pauseEvent != null)
pauseEvent.survivorRecord(new SurvivorRecord(getClock(), trace.getLongGroup(1), trace.getIntegerGroup(2), trace.getIntegerGroup(3)));
}

/**
* Capture logged age table data
* @param trace
* @param line
*/
private void tenuringAgeBreakout(GCLogTrace trace, String line) {
if (pauseEvent != null)
pauseEvent.addAgeBreakout(trace.getIntegerGroup(1), trace.getLongGroup(2));
}

/**
* If the concurrentCyclePauseEvent has not been recorded, something has gone wrong and it's likely
* that it doesn't have a consistent state. The default action is to lose it.
Expand Down Expand Up @@ -449,13 +472,14 @@ private GenerationalGCPauseEvent buildYoungEvent(GenerationalForwardReference fo
youngCollection = new PSYoungGen(forwardReference.getStartTime(), forwardReference.getGCCause(), forwardReference.getDuration());
break;
default:
LOGGER.warning(forwardReference.getGarbageCollectionType() + " not recognized");
throw new IllegalStateException(forwardReference.getGarbageCollectionType() + " not recognized");
}

fillOutMemoryPoolData(youngCollection, forwardReference);
fillOutMetaspaceData(youngCollection, forwardReference);
youngCollection.add(forwardReference.getCPUSummary());
// add in reference processing
youngCollection.add(forwardReference.getSurvivorRecord());
// todo: add in reference processing
return youngCollection;
}

Expand Down Expand Up @@ -519,7 +543,7 @@ private GenerationalGCPauseEvent buildPauseEvent(GenerationalForwardReference fo
return buildInitialMark(forwardReference);
case Remark:
return buildRemark(forwardReference);
case PSFull: //todo:
case PSFull:
case FullGC:
case Full:
return buildFullGC(forwardReference);
Expand Down Expand Up @@ -565,8 +589,7 @@ private boolean ignoreFrequentlySeenButUnwantedLines(String line) {
if (line.contains("exit"))
if (line.contains("used")) return true;
if (line.contains("workers")) return true;
if (line.contains("Heap address")) return true;
return line.contains("Desired") || line.contains("Age table") || line.contains("- age ");
return line.contains("Heap address");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import static com.microsoft.gctoolkit.parser.CommonTestHelper.captureTest;
import static org.junit.jupiter.api.Assertions.*;

public class G1GCUnifiedParserRulesTest implements UnifiedG1GCPatterns {
public class G1GCUnifiedParserRulesTest implements UnifiedG1GCPatterns, TenuredPatterns {

/**
* The rules are;
Expand Down Expand Up @@ -152,7 +152,9 @@ private void evaluate(GCParseRule rule, String string, boolean dump) {
WEAK_PROCESSING,
CLEANUP__FINALIZE_CONC_MARK,
CONCURRENT_UNDO_CYCLE_START,
CONCURRENT_UNDO_CYCLE_END // 70
CONCURRENT_UNDO_CYCLE_END , // 70
TENURING_SUMMARY,
TENURING_AGE_BREAKDOWN
};

/*
Expand Down Expand Up @@ -446,6 +448,12 @@ private void evaluate(GCParseRule rule, String string, boolean dump) {
},
{ // 70
"[155.836s][info ][gc ] GC(2457) Concurrent Undo Cycle 49.351ms",
},
{ // 71
"[10.749s][debug][gc,age ] GC(0) Desired survivor size 1572864 bytes, new threshold 15 (max threshold 15)\n"
},
{ // 72
"[10.754s][trace][gc,age ] GC(0) - age 1: 2579584 bytes, 2579584 total"
}

// Remaining lines which may not need to be parsed...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import static com.microsoft.gctoolkit.parser.CommonTestHelper.captureTest;
import static org.junit.jupiter.api.Assertions.*;

public class GenerationalHeapParserRulesTest implements SimplePatterns, SerialPatterns, ParallelPatterns, CMSPatterns, ICMSPatterns {
public class GenerationalHeapParserRulesTest implements SimplePatterns, SerialPatterns, ParallelPatterns, CMSPatterns, ICMSPatterns, TenuredPatterns {

private static final Logger LOGGER = Logger.getLogger(GenerationalHeapParserRulesTest.class.getName());

Expand Down Expand Up @@ -250,7 +250,9 @@ private void evaluate(GCParseRule rule, String string, boolean dump) {
// CMF_LARGE_BLOCK,
// //this rule must be evaluated before CONCURRENT_PHASE_END_BLOCK
// ABORT_PRECLEAN_DUE_TO_TIME_CLAUSE,
PRECLEAN_REFERENCE
PRECLEAN_REFERENCE,
TENURING_SUMMARY,
TENURING_AGE_BREAKDOWN
};

private String[][] lines = {
Expand Down Expand Up @@ -591,6 +593,12 @@ private void evaluate(GCParseRule rule, String string, boolean dump) {
// },
{
"2016-04-01T15:03:42.171-0700: 11025.637: [Preclean SoftReferences, 0.0000530 secs]2016-04-01T15:03:42.172-0700: 11025.637: [Preclean WeakReferences, 0.0006860 secs]2016-04-01T15:03:42.172-0700: 11025.638: [Preclean FinalReferences, 0.0005450 secs]2016-04-01T15:03:42.173-0700: 11025.639: [Preclean PhantomReferences, 0.0000230 secs]2016-04-01T15:03:42.197-0700: 11025.663: [CMS-concurrent-preclean: 0.025/0.026 secs] [Times: user=0.04 sys=0.01, real=0.03 secs]"
},
{
"[10.749s][debug][gc,age ] GC(0) Desired survivor size 1572864 bytes, new threshold 15 (max threshold 15)\n"
},
{
"[10.754s][trace][gc,age ] GC(0) - age 1: 2579584 bytes, 2579584 total"
}
};
}
Loading