Skip to content

Commit eb2676f

Browse files
committed
Merge branch 'pr/cuiweiloong/enhance-support-for-zgc-and-shenandoah' into develop
2 parents d74690e + cb5d0ee commit eb2676f

23 files changed

+1640
-478
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ GCViewer 1.36
33

44
[![Build Status](https://app.travis-ci.com/chewiebug/GCViewer.svg?branch=develop)](https://app.travis-ci.com/chewiebug/GCViewer)
55
[![codecov.io](https://codecov.io/github/chewiebug/GCViewer/coverage.svg?branch=develop)](https://codecov.io/github/chewiebug/GCViewer?branch=develop)
6-
[![Download gcviewer](https://img.shields.io/sourceforge/dm/gcviewer.svg)](https://sourceforge.net/projects/gcviewer/files/latest/download)
6+
[![Download gcviewer](https://img.shields.io/sourceforge/dm/gcviewer.svg)](https://sourceforge.net/projects/gcviewer/files)
77

88
GCViewer is a little tool that visualizes verbose GC output
99
generated by Sun / Oracle, IBM, HP and BEA Java Virtual Machines. It

pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@
180180
<name>Pierre Viret</name>
181181
<url>https://github.com/pierre-viret</url>
182182
</developer>
183+
<developer>
184+
<name>Cui Weiloong</name>
185+
<url>https://github.com/CuiWeiloong</url>
186+
</developer>
183187
<developer>
184188
<name>Yin Xunjun</name>
185189
</developer>

src/main/java/com/tagtraum/perf/gcviewer/exp/impl/SummaryDataWriter.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
import java.io.PrintWriter;
77
import java.text.NumberFormat;
88
import java.util.Date;
9+
import java.util.List;
910
import java.util.Map;
11+
import java.util.Map.Entry;
1012

1113
import com.tagtraum.perf.gcviewer.exp.AbstractDataWriter;
14+
import com.tagtraum.perf.gcviewer.math.DoubleData;
15+
import com.tagtraum.perf.gcviewer.math.DoubleDataPercentile;
1216
import com.tagtraum.perf.gcviewer.model.GCModel;
1317
import com.tagtraum.perf.gcviewer.util.FormattedValue;
1418
import com.tagtraum.perf.gcviewer.util.MemoryFormat;
@@ -69,7 +73,7 @@ public SummaryDataWriter(OutputStream out, Map<String, Object> configuration) {
6973

7074
private void initialiseFormatters() {
7175
pauseFormatter = NumberFormat.getInstance();
72-
pauseFormatter.setMaximumFractionDigits(5);
76+
pauseFormatter.setMaximumFractionDigits(6);
7377

7478
totalTimeFormatter = new TimeFormat();
7579

@@ -227,6 +231,74 @@ private void exportPauseSummary(PrintWriter out, GCModel model) {
227231
exportValue(out, "fullGCPausePc", percentFormatter.format(model.getFullGCPause().getSum()*100.0/model.getPause().getSum()), "%");
228232
exportValue(out, "gcPause", gcTimeFormatter.format(model.getGCPause().getSum()), "s");
229233
exportValue(out, "gcPausePc", percentFormatter.format(model.getGCPause().getSum()*100.0/model.getPause().getSum()), "%");
234+
235+
// Add extra statistical data: sum, count, min, max, average, standardDeviation, median, 75th percentile, 95, 99, 99.5, 99.9
236+
// All Pause stats
237+
if (pauseDataAvailable) {
238+
exportValue(out, "pauseSum", pauseFormatter.format(model.getPause().getSum()), "s");
239+
// exportValue(out, "pauseCount", "" + model.getPause().getN(), "-");
240+
exportValue(out, "pauseMin", pauseFormatter.format(model.getPause().getMin()), "s");
241+
exportValue(out, "pauseMax", pauseFormatter.format(model.getPause().getMax()), "s");
242+
exportValue(out, "pauseAverage", pauseFormatter.format(model.getPause().average()), "s");
243+
exportValue(out, "pauseStandardDeviation", pauseFormatter.format(model.getPause().standardDeviation()), "s");
244+
exportValue(out, "pauseMedian", pauseFormatter.format(((DoubleDataPercentile)model.getPause()).getPercentile(50)), "s");
245+
exportValue(out, "pausePercentile75th", pauseFormatter.format(((DoubleDataPercentile)model.getPause()).getPercentile(50)), "s");
246+
exportValue(out, "pausePercentile95th", pauseFormatter.format(((DoubleDataPercentile)model.getPause()).getPercentile(75)), "s");
247+
exportValue(out, "pausePercentile99th", pauseFormatter.format(((DoubleDataPercentile)model.getPause()).getPercentile(95)), "s");
248+
exportValue(out, "pausePercentile99.5th", pauseFormatter.format(((DoubleDataPercentile)model.getPause()).getPercentile(99)), "s");
249+
exportValue(out, "pausePercentile99.9th", pauseFormatter.format(((DoubleDataPercentile)model.getPause()).getPercentile(99.9)), "s");
250+
}
251+
// GC Pause stats
252+
if (gcDataAvailable) {
253+
exportValue(out, "gcPauseSum", pauseFormatter.format(model.getGCPause().getSum()), "s");
254+
// exportValue(out, "gcPauseCount", "" + model.getGCPause().getN(), "-");
255+
exportValue(out, "gcPauseMin", pauseFormatter.format(model.getGCPause().getMin()), "s");
256+
exportValue(out, "gcPauseMax", pauseFormatter.format(model.getGCPause().getMax()), "s");
257+
exportValue(out, "gcPauseAverage", pauseFormatter.format(model.getGCPause().average()), "s");
258+
exportValue(out, "gcPauseStandardDeviation", pauseFormatter.format(model.getGCPause().standardDeviation()), "s");
259+
exportValue(out, "gcPauseMedian", pauseFormatter.format(((DoubleDataPercentile)model.getGCPause()).getPercentile(50)), "s");
260+
exportValue(out, "gcPausePercentile75th", pauseFormatter.format(((DoubleDataPercentile)model.getGCPause()).getPercentile(50)), "s");
261+
exportValue(out, "gcPausePercentile95th", pauseFormatter.format(((DoubleDataPercentile)model.getGCPause()).getPercentile(75)), "s");
262+
exportValue(out, "gcPausePercentile99th", pauseFormatter.format(((DoubleDataPercentile)model.getGCPause()).getPercentile(95)), "s");
263+
exportValue(out, "gcPausePercentile99.5th", pauseFormatter.format(((DoubleDataPercentile)model.getGCPause()).getPercentile(99)), "s");
264+
exportValue(out, "gcPausePercentile99.9th", pauseFormatter.format(((DoubleDataPercentile)model.getGCPause()).getPercentile(99.9)), "s");
265+
}
266+
// Full GC Pause stats
267+
if (fullGCDataAvailable) {
268+
exportValue(out, "fullGCPauseSum", pauseFormatter.format(model.getFullGCPause().getSum()), "s");
269+
// exportValue(out, "fullGCPauseCount", "" + model.getFullGCPause().getN(), "-");
270+
exportValue(out, "fullGCPauseMin", pauseFormatter.format(model.getFullGCPause().getMin()), "s");
271+
exportValue(out, "fullGCPauseMax", pauseFormatter.format(model.getFullGCPause().getMax()), "s");
272+
exportValue(out, "fullGCPauseAverage", pauseFormatter.format(model.getFullGCPause().average()), "s");
273+
exportValue(out, "fullGCPauseStandardDeviation", pauseFormatter.format(model.getFullGCPause().standardDeviation()), "s");
274+
exportValue(out, "fullGCPauseMedian", pauseFormatter.format(((DoubleDataPercentile)model.getFullGCPause()).getPercentile(50)), "s");
275+
exportValue(out, "fullGCPausePercentile75th", pauseFormatter.format(((DoubleDataPercentile)model.getFullGCPause()).getPercentile(50)), "s");
276+
exportValue(out, "fullGCPausePercentile95th", pauseFormatter.format(((DoubleDataPercentile)model.getFullGCPause()).getPercentile(75)), "s");
277+
exportValue(out, "fullGCPausePercentile99th", pauseFormatter.format(((DoubleDataPercentile)model.getFullGCPause()).getPercentile(95)), "s");
278+
exportValue(out, "fullGCPausePercentile99.5th", pauseFormatter.format(((DoubleDataPercentile)model.getFullGCPause()).getPercentile(99)), "s");
279+
exportValue(out, "fullGCPausePercentile99.9th", pauseFormatter.format(((DoubleDataPercentile)model.getFullGCPause()).getPercentile(99.9)), "s");
280+
}
281+
// ZGC stats: [gc,phases]
282+
if (model.size() > 1 && model.getGcEventPhases().size() > 0) {
283+
DoubleData gcPhases = new DoubleDataPercentile();
284+
for (Entry<String, DoubleData> entry : model.getGcEventPhases().entrySet()) {
285+
List<Double> phaseList = ((DoubleDataPercentile)entry.getValue()).getDoubleData();
286+
for (Double d : phaseList)
287+
gcPhases.add(d);
288+
}
289+
exportValue(out, "gcPhaseSum", pauseFormatter.format(gcPhases.getSum()), "s");
290+
exportValue(out, "gcPhaseCount", "" + gcPhases.getN(), "-");
291+
exportValue(out, "gcPhaseMin", pauseFormatter.format(gcPhases.getMin()), "s");
292+
exportValue(out, "gcPhaseMax", pauseFormatter.format(gcPhases.getMax()), "s");
293+
exportValue(out, "gcPhaseAverage", pauseFormatter.format(gcPhases.average()), "s");
294+
exportValue(out, "gcPhaseStandardDeviation", pauseFormatter.format(gcPhases.standardDeviation()), "s");
295+
exportValue(out, "gcPhaseMedian", pauseFormatter.format(((DoubleDataPercentile)gcPhases).getPercentile(50)), "s");
296+
exportValue(out, "gcPhasePercentile75th", pauseFormatter.format(((DoubleDataPercentile)gcPhases).getPercentile(50)), "s");
297+
exportValue(out, "gcPhasePercentile95th", pauseFormatter.format(((DoubleDataPercentile)gcPhases).getPercentile(75)), "s");
298+
exportValue(out, "gcPhasePercentile99th", pauseFormatter.format(((DoubleDataPercentile)gcPhases).getPercentile(95)), "s");
299+
exportValue(out, "gcPhasePercentile99.5th", pauseFormatter.format(((DoubleDataPercentile)gcPhases).getPercentile(99)), "s");
300+
exportValue(out, "gcPhasePercentile99.9th", pauseFormatter.format(((DoubleDataPercentile)gcPhases).getPercentile(99.9)), "s");
301+
}
230302
}
231303

232304
private boolean isSignificant(final double average, final double standardDeviation) {

src/main/java/com/tagtraum/perf/gcviewer/imp/DataReaderIBM_J9_R28.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import javax.xml.stream.events.XMLEvent;
2121

2222
import com.tagtraum.perf.gcviewer.model.AbstractGCEvent;
23+
import com.tagtraum.perf.gcviewer.model.AbstractGCEvent.ExtendedType;
2324
import com.tagtraum.perf.gcviewer.model.AbstractGCEvent.Type;
2425
import com.tagtraum.perf.gcviewer.model.GCEvent;
2526
import com.tagtraum.perf.gcviewer.model.GCModel;
@@ -92,7 +93,7 @@ public GCModel read() throws IOException {
9293
break;
9394
case EXCLUSIVE_END:
9495
handleExclusiveEnd(startElement, currentGcEvent);
95-
if (currentGcEvent.getExtendedType() == null) {
96+
if (currentGcEvent.getExtendedType() == null || currentGcEvent.getExtendedType() == ExtendedType.UNDEFINED) {
9697
if (getLogger().isLoggable(Level.FINE))
9798
getLogger().fine("event at " + in.getLineNumber() + " doesn't contain any information, the parser can handle");
9899
}

src/main/java/com/tagtraum/perf/gcviewer/imp/DataReaderSun1_6_0.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public class DataReaderSun1_6_0 extends AbstractDataReaderSun {
118118
EXCLUDE_STRINGS_LINE_START.add("/proc/meminfo"); // apple vms seem to print this out in the beginning of the logs
119119
EXCLUDE_STRINGS_LINE_START.add("Uncommitted"); // -XX:+UseShenandoahGC
120120
EXCLUDE_STRINGS_LINE_START.add("Cancelling concurrent GC"); // -XX:+UseShenandoahGC
121+
EXCLUDE_STRINGS_LINE_START.add("Cancelling GC"); // -XX:+UseShenandoahGC
121122
EXCLUDE_STRINGS_LINE_START.add("Capacity"); // -XX:+UseShenandoahGC -XX:+PrintGCDetails
122123
EXCLUDE_STRINGS_LINE_START.add("Periodic GC triggered"); // -XX:+UseShenandoahGC -XX:+PrintGCDetails
123124
EXCLUDE_STRINGS_LINE_START.add("Immediate Garbage"); // -XX:+UseShenandoahGC -XX:+PrintGCDetails
@@ -126,7 +127,6 @@ public class DataReaderSun1_6_0 extends AbstractDataReaderSun {
126127
EXCLUDE_STRINGS_LINE_START.add("Concurrent marking triggered"); // -XX:+UseShenandoahGC -XX:+PrintGCDetails
127128
EXCLUDE_STRINGS_LINE_START.add("Adjusting free threshold"); // -XX:+UseShenandoahGC
128129
EXCLUDE_STRINGS_LINE_START.add("Predicted cset threshold"); // -XX:+UseShenandoahGC
129-
EXCLUDE_STRINGS_LINE_START.add("Trigger"); // -XX:+UseShenandoahGC
130130
EXCLUDE_STRINGS_LINE_START.add("Free"); // -XX:+UseShenandoahGC
131131
EXCLUDE_STRINGS_LINE_START.add("Evacuation Reserve"); // -XX:+UseShenandoahGC
132132
EXCLUDE_STRINGS_LINE_START.add("Pacer for "); // -XX:+UseShenandoahGC
@@ -135,6 +135,9 @@ public class DataReaderSun1_6_0 extends AbstractDataReaderSun {
135135
EXCLUDE_STRINGS_LINE_START.add(" Adaptive CSet Selection"); // -XX:+UseShenandoahGC
136136
EXCLUDE_STRINGS_LINE_START.add(" Collectable Garbage"); // -XX:+UseShenandoahGC
137137
EXCLUDE_STRINGS_LINE_START.add(" Immediate Garbage"); // -XX:+UseShenandoahGC
138+
EXCLUDE_STRINGS_LINE_START.add(" Good progress for"); // -XX:+UseShenandoahGC
139+
EXCLUDE_STRINGS_LINE_START.add(" Failed to"); // -XX:+UseShenandoahGC
140+
EXCLUDE_STRINGS_LINE_START.add(" Cancelling GC"); // -XX:+UseShenandoahGC
138141

139142
EXCLUDE_STRINGS_LINE_CONTAIN.add(LOGFILE_ROLLING_BEGIN);
140143
EXCLUDE_STRINGS_LINE_CONTAIN.add(LOGFILE_ROLLING_END);
@@ -155,6 +158,8 @@ public class DataReaderSun1_6_0 extends AbstractDataReaderSun {
155158
LOG_INFORMATION_STRINGS.add("Reference processing"); // -XX:+UseShenandoahGC
156159
LOG_INFORMATION_STRINGS.add("Heuristics ergonomically sets"); // -XX:+UseShenandoahGC
157160
LOG_INFORMATION_STRINGS.add("Initialize Shenandoah heap"); // -XX:+UseShenandoahGC
161+
LOG_INFORMATION_STRINGS.add("Shenandoah GC mode"); // -XX:+UseShenandoahGC
162+
LOG_INFORMATION_STRINGS.add("Soft Max Heap Size"); // -XX:+UseShenandoahGC
158163
}
159164

160165
private static final String EVENT_YG_OCCUPANCY = "YG occupancy";
@@ -253,6 +258,8 @@ public class DataReaderSun1_6_0 extends AbstractDataReaderSun {
253258
private static final String SHENANDOAH_DETAILS_FINAL_MARK_SPLIT_START = "Total";
254259

255260
private static final String SHENANDOAH_INTRODUCTION_TO_GC_STATISTICS = "Shenandoah Heap";
261+
private static final String SHENANDOAH_GC_CYCLE_DETAILS_START = "All times are wall-clock times";
262+
private static final String SHENANDOAH_GC_CYCLE_START = "Trigger: ";
256263

257264
// -XX:+PrintReferenceGC
258265
private static final String PRINT_REFERENCE_GC_INDICATOR = "Reference";
@@ -309,9 +316,17 @@ else if (startsWith(line, LOG_INFORMATION_STRINGS, false)) {
309316
continue;
310317
} else if (line.startsWith(SHENANDOAH_INTRODUCTION_TO_GC_STATISTICS)) {
311318
// Assumption: As soon as the shenandoah gc statistics block starts, the vm is shutting down
312-
skipAndLogToEndOfFile(in);
319+
skipAndLogToEndOfFile(in, line);
320+
continue;
321+
} else if (line.startsWith(SHENANDOAH_GC_CYCLE_START)) {
322+
// skip the start string of the first gc cycle
323+
continue;
324+
} else if (line.startsWith(SHENANDOAH_GC_CYCLE_DETAILS_START)) {
325+
// ignore details of each gc cycle
326+
skipGcCycleDetails(in);
313327
continue;
314328
}
329+
315330
if (line.indexOf(CMS_ABORT_PRECLEAN) >= 0) {
316331
// line contains like " CMS: abort preclean due to time "
317332
// -> remove the text
@@ -485,13 +500,27 @@ else if (beginningOfLine.size() > 0) {
485500
}
486501
}
487502

488-
private void skipAndLogToEndOfFile(LineNumberReader in) throws IOException {
489-
String line;
503+
private void skipAndLogToEndOfFile(LineNumberReader in, String line) throws IOException {
504+
getLogger().info(line);
490505
while ((line = in.readLine()) != null) {
491506
getLogger().info(line);
492507
}
493508
}
494509

510+
private void skipGcCycleDetails(LineNumberReader in) throws IOException {
511+
String line;
512+
while ((line = in.readLine()) != null) {
513+
// parse the events for the next GC cycle
514+
if (line.startsWith(SHENANDOAH_GC_CYCLE_START)) {
515+
break;
516+
}
517+
// the vm is shutting down
518+
if (line.startsWith(SHENANDOAH_INTRODUCTION_TO_GC_STATISTICS)) {
519+
skipAndLogToEndOfFile(in, line);
520+
}
521+
}
522+
}
523+
495524
private boolean isPrintHeapAtGcStarting(String line) {
496525
return line.startsWith(HEAP) // jdk 6 and before
497526
|| line.indexOf(HEAP_SIZING_BEFORE) >= 0 // jdk 7 and after

src/main/java/com/tagtraum/perf/gcviewer/imp/DataReaderTools.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public ExtendedType parseType(String typeString) throws UnknownGcTypeException {
6969
}
7070

7171
/**
72-
* Same as @{link {@link #parseType(String)}}, but returns <code>null</code> instead of exception, if no type could
72+
* Same as {@link #parseType(String)}, but returns <code>null</code> instead of exception, if no type could
7373
* be found.
7474
*
7575
* @param typeName string representation of the gc event

0 commit comments

Comments
 (0)