Skip to content

Commit d54eae8

Browse files
author
cuiweilong
committed
add percentiles in output csv file
1 parent e5c31e1 commit d54eae8

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

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/math/DoubleDataPercentile.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,12 @@ else if (percentile > 100) {
4444
}
4545
return doubleSet.get((int)position-1);
4646
}
47+
48+
/**
49+
* return all double data.
50+
* @return list of double data
51+
*/
52+
public List<Double> getDoubleData() {
53+
return this.doubleSet;
54+
}
4755
}

src/main/java/com/tagtraum/perf/gcviewer/model/GCModel.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ public GCModel() {
201201
this.postFullGCUsedHeap = new IntData();
202202

203203
this.postGCUsedMemory = new IntData();
204-
this.totalPause = new DoubleData();
205-
this.fullGCPause = new DoubleData();
204+
this.totalPause = new DoubleDataPercentile();
205+
this.fullGCPause = new DoubleDataPercentile();
206206
this.fullGcPauseInterval = new DoubleData();
207207
this.gcPause = new DoubleDataPercentile();
208208
this.vmOperationPause = new DoubleData();

src/test/java/com/tagtraum/perf/gcviewer/exp/SummaryDataWriterTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import com.tagtraum.perf.gcviewer.exp.impl.SummaryDataWriter;
1313
import com.tagtraum.perf.gcviewer.imp.DataReader;
14+
import com.tagtraum.perf.gcviewer.imp.DataReaderFactory;
1415
import com.tagtraum.perf.gcviewer.imp.DataReaderSun1_6_0;
1516
import com.tagtraum.perf.gcviewer.imp.GcLogType;
1617
import com.tagtraum.perf.gcviewer.model.AbstractGCEvent.Type;
@@ -140,4 +141,40 @@ public void testWriteWithPromotion() throws IOException {
140141

141142
assertThat("avgPromotion", csv, Matchers.containsString("avgPromotion; " + memoryFormatter.formatToFormatted(2925).getValue() + "; K"));
142143
}
144+
145+
@Test
146+
public void testWriteWithZGCPhases() throws IOException {
147+
ByteArrayInputStream in = new ByteArrayInputStream(
148+
("[2022-08-18T17:18:46.761+0800][0.053s][info][gc ] Using The Z Garbage Collector\n" +
149+
"[2022-08-18T17:18:47.977+0800][1.269s][info][gc,start ] GC(0) Garbage Collection (Warmup)\n" +
150+
"[2022-08-18T17:18:47.978+0800][1.270s][info][gc,phases] GC(0) Pause Mark Start 0.385ms\n" +
151+
"[2022-08-18T17:18:47.985+0800][1.277s][info][gc,phases] GC(0) Concurrent Mark 7.383ms\n" +
152+
"[2022-08-18T17:18:47.985+0800][1.277s][info][gc,phases] GC(0) Pause Mark End 0.050ms\n" +
153+
"[2022-08-18T17:18:47.986+0800][1.277s][info][gc,phases] GC(0) Concurrent Process Non-Strong References 0.239ms\n" +
154+
"[2022-08-18T17:18:47.986+0800][1.277s][info][gc,phases] GC(0) Concurrent Reset Relocation Set 0.000ms\n" +
155+
"[2022-08-18T17:18:47.986+0800][1.278s][info][gc,phases] GC(0) Concurrent Destroy Detached Pages 0.174ms\n" +
156+
"[2022-08-18T17:18:47.989+0800][1.281s][info][gc,phases] GC(0) Concurrent Select Relocation Set 3.505ms\n" +
157+
"[2022-08-18T17:18:47.990+0800][1.282s][info][gc,phases] GC(0) Concurrent Prepare Relocation Set 0.760ms\n" +
158+
"[2022-08-18T17:18:47.991+0800][1.282s][info][gc,phases] GC(0) Pause Relocate Start 0.499ms\n" +
159+
"[2022-08-18T17:18:47.994+0800][1.286s][info][gc,phases] GC(0) Concurrent Relocate 3.545ms\n" +
160+
"[2022-08-18T17:18:47.994+0800][1.286s][info][gc ] GC(0) Garbage Collection (Warmup) 434M(11%)->32M(1%)")
161+
.getBytes());
162+
DataReader reader = new DataReaderFactory().getDataReader(new GcResourceFile("byteArray"), in);
163+
GCModel model = reader.read();
164+
model.setURL(new URL("file", "localhost", "test-file"));
165+
166+
ByteArrayOutputStream output = new ByteArrayOutputStream();
167+
SummaryDataWriter objectUnderTest = new SummaryDataWriter(output);
168+
169+
objectUnderTest.write(model);
170+
171+
String csv = output.toString();
172+
173+
assertThat("pausePercentile75th", csv, Matchers.containsString("pausePercentile75th; 0,000934; s"));
174+
assertThat("gcPausePercentile95th", csv, Matchers.containsString("gcPausePercentile95th; 0,000934; s"));
175+
assertThat("pauseCount", csv, Matchers.containsString("pauseCount; 1; -"));
176+
assertThat("gcPhaseCount", csv, Matchers.containsString("gcPhaseCount; 3; -"));
177+
assertThat("gcPhaseAverage", csv, Matchers.containsString("gcPhaseAverage; 0,000311; s"));
178+
assertThat("gcPhasePercentile99th", csv, Matchers.containsString("gcPhasePercentile99th; 0,000499; s"));
179+
}
143180
}

0 commit comments

Comments
 (0)