Skip to content

Commit

Permalink
Merge branch 'pull/chewiebug#196/golang' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
chewiebug committed Jul 26, 2018
2 parents 200da55 + bc52791 commit 4511323
Show file tree
Hide file tree
Showing 9 changed files with 802 additions and 1 deletion.
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
<developer>
<name>Michi Gysel</name>
</developer>
<developer>
<name>Roland Illig</name>
<url>https://github.com/rillig</url>
</developer>
<developer>
<name>Johan Kaving</name>
</developer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ else if (s.contains("starting collection, threshold allocation reached.")) {
if (getLogger().isLoggable(Level.INFO)) getLogger().info("File format: IBM i5/OS 1.4.2");
return new DataReaderIBMi5OS1_4_2(gcResource, in);
}
else if (s.contains("\ngc ")) {
if (getLogger().isLoggable(Level.INFO)) getLogger().info("File format: Go");
return new DataReaderGo(gcResource, in);
}
return null;
}

Expand Down
89 changes: 89 additions & 0 deletions src/main/java/com/tagtraum/perf/gcviewer/imp/DataReaderGo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.tagtraum.perf.gcviewer.imp;

import com.tagtraum.perf.gcviewer.model.AbstractGCEvent;
import com.tagtraum.perf.gcviewer.model.GCEvent;
import com.tagtraum.perf.gcviewer.model.GCModel;
import com.tagtraum.perf.gcviewer.model.GCResource;
import com.tagtraum.perf.gcviewer.util.ParseInformation;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Parses GC log output from Go 1.9.
*
* @author <a href="mailto:[email protected]">Roland Illig</a>
* @see <a href="https://golang.org/pkg/runtime/#hdr-Environment_Variables">Go documentation</a>
*/
public class DataReaderGo extends AbstractDataReader {

private static final Pattern GCLINE = Pattern.compile(""
+ "gc "
+ "(\\d+) "
+ "@(\\d+\\.\\d+)s "
+ "(\\d+)%: "
+ "(\\d+(?:\\.\\d+)?)\\+"
+ "(\\d+(?:\\.\\d+)?)\\+"
+ "(\\d+(?:\\.\\d+)?) ms clock, "
+ "(\\d+(?:\\.\\d+)?)\\+"
+ "(\\d+(?:\\.\\d+)?)/"
+ "(\\d+(?:\\.\\d+)?)/"
+ "(\\d+(?:\\.\\d+)?)\\+"
+ "(\\d+(?:\\.\\d+)?) ms cpu, "
+ "(\\d+)->"
+ "(\\d+)->"
+ "(\\d+) MB, "
+ "(\\d+) MB goal, "
+ "(\\d+) P");

public DataReaderGo(GCResource gcResource, InputStream in) throws UnsupportedEncodingException {
super(gcResource, in);
}

public GCModel read() throws IOException {
if (getLogger().isLoggable(Level.INFO)) getLogger().info("Reading Go format...");

try (LineNumberReader in = this.in) {
GCModel model = new GCModel();
model.setFormat(GCModel.Format.GO);
ParseInformation parsePosition = new ParseInformation(0);

Matcher matcher = GCLINE.matcher("");
String line;
while ((line = in.readLine()) != null && shouldContinue()) {
parsePosition.setIndex(0);
parsePosition.setLineNumber(in.getLineNumber());
if (!matcher.reset(line).matches()) {
continue;
}

try {
AbstractGCEvent<?> gcEvent = parseMatch(matcher);
model.add(gcEvent);
} catch (Exception pe) {
if (getLogger().isLoggable(Level.WARNING)) getLogger().warning(pe.toString());
if (getLogger().isLoggable(Level.FINE)) getLogger().log(Level.FINE, pe.getMessage(), pe);
}
}
return model;
} finally {
if (getLogger().isLoggable(Level.INFO)) getLogger().info("Done reading.");
}
}

private AbstractGCEvent<?> parseMatch(Matcher matcher) {
double relativeTime = Double.parseDouble(matcher.group(2));
double stopTheWorld1Time = Double.parseDouble(matcher.group(4)) / 1000.0;
double stopTheWorld2Time = Double.parseDouble(matcher.group(6)) / 1000.0;
int preUsed = Integer.parseInt(matcher.group(12)) * 1024;
int alive = Integer.parseInt(matcher.group(13)) * 1024;
int postUsed = Integer.parseInt(matcher.group(14)) * 1024;

double pause = stopTheWorld1Time + stopTheWorld2Time;
return new GCEvent(relativeTime, preUsed, postUsed, alive, pause, AbstractGCEvent.Type.GC);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1065,5 +1065,6 @@ public String toString() {
public static final Format IBM_VERBOSE_GC = new Format("IBM -verbose:gc");
public static final Format SUN_1_2_2VERBOSE_GC = new Format("Sun 1.2.2 -verbose:gc");
public static final Format UNIFIED_JVM_LOGGING = new Format("Unified jvm logging -Xlog:gc");
public static final Format GO = new Format("Go");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
Expand Down Expand Up @@ -48,6 +47,7 @@ public class AboutDialog extends ScreenCenteredDialog implements ActionListener
"Neil Gentleman",
"Chris Grindstaff",
"Michi Gysel",
"Roland Illig",
"Johan Kaving",
"Maciej Kwiecien",
"Henry Lin",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class UnittestHelper {

private static final String FOLDER_OPENJDK = "openjdk";
public enum FOLDER {
GO("go"),
HP("hp"),
IBM("ibm"),
JROCKIT("jrockit"),
Expand Down
63 changes: 63 additions & 0 deletions src/test/java/com/tagtraum/perf/gcviewer/imp/TestDataReaderGo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.tagtraum.perf.gcviewer.imp;

import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;

import com.tagtraum.perf.gcviewer.UnittestHelper;
import com.tagtraum.perf.gcviewer.model.AbstractGCEvent;
import com.tagtraum.perf.gcviewer.model.GCModel;
import com.tagtraum.perf.gcviewer.model.GCResource;
import com.tagtraum.perf.gcviewer.model.GcResourceFile;
import org.junit.Test;

public class TestDataReaderGo {

@Test
public void test() throws IOException {
TestLogHandler handler = new TestLogHandler();
handler.setLevel(Level.WARNING);
GCResource gcResource = new GcResourceFile("byteArray");
gcResource.getLogger().addHandler(handler);

String gcLog = ""
+ "gc starting...\n" // Such a line is not produced by the Go GC; it is just for testing
+ "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"
+ "a line unrelated to GC logging\n"
+ "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"
+ "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";
ByteArrayInputStream in = new ByteArrayInputStream(gcLog.getBytes("US-ASCII"));
DataReader reader = new DataReaderGo(gcResource, in);
GCModel model = reader.read();

assertThat("gc 2 -> warning", handler.getCount(), is(1));
assertThat("size", model.size(), is(2));

AbstractGCEvent<?> event1 = model.get(0);
assertThat("timestamp", event1.getTimestamp(), closeTo(0.058, 0.0001));
assertThat("pause", event1.getPause(), closeTo(0 + 0, 0.1));
assertThat("preused", event1.getPreUsed(), is(4096));
assertThat("postused", event1.getPostUsed(), is(1024));
assertThat("heap", event1.getTotal(), is(5120));
}

@Test
public void exampleLog() throws IOException {
TestLogHandler handler = new TestLogHandler();
handler.setLevel(Level.WARNING);
GCResource gcResource = new GcResourceFile("go1.9.txt");
gcResource.getLogger().addHandler(handler);

InputStream in = UnittestHelper.getResourceAsStream(UnittestHelper.FOLDER.GO, gcResource.getResourceName());
DataReader reader = new DataReaderGo(gcResource, in);
GCModel model = reader.read();

assertThat("warnings", handler.getCount(), is(0));
assertThat("size", model.size(), is(635));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public void fullGcWithDetailedSizes() throws Exception {
TestLogHandler handler = new TestLogHandler();
handler.setLevel(Level.WARNING);
GCResource gcResource = new GcResourceFile("byteArray");
gcResource.getLogger().addHandler(handler);

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

0 comments on commit 4511323

Please sign in to comment.