Skip to content

Commit ebf5f8e

Browse files
committed
Merge branch 'pull/#196/golang' into develop
2 parents 49b70ae + a7ae4d2 commit ebf5f8e

File tree

9 files changed

+802
-1
lines changed

9 files changed

+802
-1
lines changed

pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959
<developer>
6060
<name>Michi Gysel</name>
6161
</developer>
62+
<developer>
63+
<name>Roland Illig</name>
64+
<url>https://github.com/rillig</url>
65+
</developer>
6266
<developer>
6367
<name>Johan Kaving</name>
6468
</developer>

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

+4
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ else if (s.contains("starting collection, threshold allocation reached.")) {
207207
if (getLogger().isLoggable(Level.INFO)) getLogger().info("File format: IBM i5/OS 1.4.2");
208208
return new DataReaderIBMi5OS1_4_2(gcResource, in);
209209
}
210+
else if (s.contains("\ngc ")) {
211+
if (getLogger().isLoggable(Level.INFO)) getLogger().info("File format: Go");
212+
return new DataReaderGo(gcResource, in);
213+
}
210214
return null;
211215
}
212216

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.tagtraum.perf.gcviewer.imp;
2+
3+
import com.tagtraum.perf.gcviewer.model.AbstractGCEvent;
4+
import com.tagtraum.perf.gcviewer.model.GCEvent;
5+
import com.tagtraum.perf.gcviewer.model.GCModel;
6+
import com.tagtraum.perf.gcviewer.model.GCResource;
7+
import com.tagtraum.perf.gcviewer.util.ParseInformation;
8+
import java.io.IOException;
9+
import java.io.InputStream;
10+
import java.io.LineNumberReader;
11+
import java.io.UnsupportedEncodingException;
12+
import java.util.logging.Level;
13+
import java.util.regex.Matcher;
14+
import java.util.regex.Pattern;
15+
16+
/**
17+
* Parses GC log output from Go 1.9.
18+
*
19+
* @author <a href="mailto:[email protected]">Roland Illig</a>
20+
* @see <a href="https://golang.org/pkg/runtime/#hdr-Environment_Variables">Go documentation</a>
21+
*/
22+
public class DataReaderGo extends AbstractDataReader {
23+
24+
private static final Pattern GCLINE = Pattern.compile(""
25+
+ "gc "
26+
+ "(\\d+) "
27+
+ "@(\\d+\\.\\d+)s "
28+
+ "(\\d+)%: "
29+
+ "(\\d+(?:\\.\\d+)?)\\+"
30+
+ "(\\d+(?:\\.\\d+)?)\\+"
31+
+ "(\\d+(?:\\.\\d+)?) ms clock, "
32+
+ "(\\d+(?:\\.\\d+)?)\\+"
33+
+ "(\\d+(?:\\.\\d+)?)/"
34+
+ "(\\d+(?:\\.\\d+)?)/"
35+
+ "(\\d+(?:\\.\\d+)?)\\+"
36+
+ "(\\d+(?:\\.\\d+)?) ms cpu, "
37+
+ "(\\d+)->"
38+
+ "(\\d+)->"
39+
+ "(\\d+) MB, "
40+
+ "(\\d+) MB goal, "
41+
+ "(\\d+) P");
42+
43+
public DataReaderGo(GCResource gcResource, InputStream in) throws UnsupportedEncodingException {
44+
super(gcResource, in);
45+
}
46+
47+
public GCModel read() throws IOException {
48+
if (getLogger().isLoggable(Level.INFO)) getLogger().info("Reading Go format...");
49+
50+
try (LineNumberReader in = this.in) {
51+
GCModel model = new GCModel();
52+
model.setFormat(GCModel.Format.GO);
53+
ParseInformation parsePosition = new ParseInformation(0);
54+
55+
Matcher matcher = GCLINE.matcher("");
56+
String line;
57+
while ((line = in.readLine()) != null && shouldContinue()) {
58+
parsePosition.setIndex(0);
59+
parsePosition.setLineNumber(in.getLineNumber());
60+
if (!matcher.reset(line).matches()) {
61+
continue;
62+
}
63+
64+
try {
65+
AbstractGCEvent<?> gcEvent = parseMatch(matcher);
66+
model.add(gcEvent);
67+
} catch (Exception pe) {
68+
if (getLogger().isLoggable(Level.WARNING)) getLogger().warning(pe.toString());
69+
if (getLogger().isLoggable(Level.FINE)) getLogger().log(Level.FINE, pe.getMessage(), pe);
70+
}
71+
}
72+
return model;
73+
} finally {
74+
if (getLogger().isLoggable(Level.INFO)) getLogger().info("Done reading.");
75+
}
76+
}
77+
78+
private AbstractGCEvent<?> parseMatch(Matcher matcher) {
79+
double relativeTime = Double.parseDouble(matcher.group(2));
80+
double stopTheWorld1Time = Double.parseDouble(matcher.group(4)) / 1000.0;
81+
double stopTheWorld2Time = Double.parseDouble(matcher.group(6)) / 1000.0;
82+
int preUsed = Integer.parseInt(matcher.group(12)) * 1024;
83+
int alive = Integer.parseInt(matcher.group(13)) * 1024;
84+
int postUsed = Integer.parseInt(matcher.group(14)) * 1024;
85+
86+
double pause = stopTheWorld1Time + stopTheWorld2Time;
87+
return new GCEvent(relativeTime, preUsed, postUsed, alive, pause, AbstractGCEvent.Type.GC);
88+
}
89+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -1065,5 +1065,6 @@ public String toString() {
10651065
public static final Format IBM_VERBOSE_GC = new Format("IBM -verbose:gc");
10661066
public static final Format SUN_1_2_2VERBOSE_GC = new Format("Sun 1.2.2 -verbose:gc");
10671067
public static final Format UNIFIED_JVM_LOGGING = new Format("Unified jvm logging -Xlog:gc");
1068+
public static final Format GO = new Format("Go");
10681069
}
10691070
}

src/main/java/com/tagtraum/perf/gcviewer/view/AboutDialog.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.awt.Panel;
1111
import java.awt.event.ActionEvent;
1212
import java.awt.event.ActionListener;
13-
1413
import javax.swing.BorderFactory;
1514
import javax.swing.ImageIcon;
1615
import javax.swing.JButton;
@@ -48,6 +47,7 @@ public class AboutDialog extends ScreenCenteredDialog implements ActionListener
4847
"Neil Gentleman",
4948
"Chris Grindstaff",
5049
"Michi Gysel",
50+
"Roland Illig",
5151
"Johan Kaving",
5252
"Maciej Kwiecien",
5353
"Henry Lin",

src/test/java/com/tagtraum/perf/gcviewer/UnittestHelper.java

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class UnittestHelper {
3131

3232
private static final String FOLDER_OPENJDK = "openjdk";
3333
public enum FOLDER {
34+
GO("go"),
3435
HP("hp"),
3536
IBM("ibm"),
3637
JROCKIT("jrockit"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.tagtraum.perf.gcviewer.imp;
2+
3+
import static org.hamcrest.Matchers.closeTo;
4+
import static org.hamcrest.Matchers.is;
5+
import static org.junit.Assert.assertThat;
6+
7+
import java.io.ByteArrayInputStream;
8+
import java.io.IOException;
9+
import java.io.InputStream;
10+
import java.util.logging.Level;
11+
12+
import com.tagtraum.perf.gcviewer.UnittestHelper;
13+
import com.tagtraum.perf.gcviewer.model.AbstractGCEvent;
14+
import com.tagtraum.perf.gcviewer.model.GCModel;
15+
import com.tagtraum.perf.gcviewer.model.GCResource;
16+
import com.tagtraum.perf.gcviewer.model.GcResourceFile;
17+
import org.junit.Test;
18+
19+
public class TestDataReaderGo {
20+
21+
@Test
22+
public void test() throws IOException {
23+
TestLogHandler handler = new TestLogHandler();
24+
handler.setLevel(Level.WARNING);
25+
GCResource gcResource = new GcResourceFile("byteArray");
26+
gcResource.getLogger().addHandler(handler);
27+
28+
String gcLog = ""
29+
+ "gc starting...\n" // Such a line is not produced by the Go GC; it is just for testing
30+
+ "gc 1 @0.058s 0%: 0+1.9+0 ms clock, 0+0.94/1.9/2.9+0 ms cpu, 4->5->1 MB, 5 MB goal, 4 P\n"
31+
+ "a line unrelated to GC logging\n"
32+
+ "gc 2 @0.073s 3%: 68+0.36+0.51 ms clock, 205+0/16/89+1.5 ms cpu, 11111111111111111111111111111111111->84->42 MB, 86 MB goal, 3 P\n"
33+
+ "gc 58 @17.837s 0%: 0.48+17+0 ms clock, 1.9+9.3/7.9/15+0 ms cpu, 30->30->15 MB, 31 MB goal, 4 P\n";
34+
ByteArrayInputStream in = new ByteArrayInputStream(gcLog.getBytes("US-ASCII"));
35+
DataReader reader = new DataReaderGo(gcResource, in);
36+
GCModel model = reader.read();
37+
38+
assertThat("gc 2 -> warning", handler.getCount(), is(1));
39+
assertThat("size", model.size(), is(2));
40+
41+
AbstractGCEvent<?> event1 = model.get(0);
42+
assertThat("timestamp", event1.getTimestamp(), closeTo(0.058, 0.0001));
43+
assertThat("pause", event1.getPause(), closeTo(0 + 0, 0.1));
44+
assertThat("preused", event1.getPreUsed(), is(4096));
45+
assertThat("postused", event1.getPostUsed(), is(1024));
46+
assertThat("heap", event1.getTotal(), is(5120));
47+
}
48+
49+
@Test
50+
public void exampleLog() throws IOException {
51+
TestLogHandler handler = new TestLogHandler();
52+
handler.setLevel(Level.WARNING);
53+
GCResource gcResource = new GcResourceFile("go1.9.txt");
54+
gcResource.getLogger().addHandler(handler);
55+
56+
InputStream in = UnittestHelper.getResourceAsStream(UnittestHelper.FOLDER.GO, gcResource.getResourceName());
57+
DataReader reader = new DataReaderGo(gcResource, in);
58+
GCModel model = reader.read();
59+
60+
assertThat("warnings", handler.getCount(), is(0));
61+
assertThat("size", model.size(), is(635));
62+
}
63+
}

src/test/java/com/tagtraum/perf/gcviewer/imp/TestDataReaderSun1_8_0G1.java

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public void fullGcWithDetailedSizes() throws Exception {
6464
TestLogHandler handler = new TestLogHandler();
6565
handler.setLevel(Level.WARNING);
6666
GCResource gcResource = new GcResourceFile("byteArray");
67+
gcResource.getLogger().addHandler(handler);
6768

6869
ByteArrayInputStream in = new ByteArrayInputStream(
6970
("2014-07-24T13:49:45.090+0400: 92457.841: [Full GC (Allocation Failure) 5811M->3097M(12G), 8.9862292 secs]"

0 commit comments

Comments
 (0)