由于对Java程序作性能测试,往往要分析gclog。
一般使用的工具为gcviewer。
但是想把gcviewer显示的结果截图到文档中又显得很不好看。
所以利用gcviewer里读取gclog的部分代码作了个,将gclog信息输出到csv文件的工具。
以便用Excel将csv打开,用Excel做出自己想要的gclog分析的图来。
关键代码
BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File( gclog文件路径)));
final DataReader reader = factory.getDataReader(in);
final GCModel model = reader.read();
for (Iterator i = model.getGCEvents(); i.hasNext();) {
GCEvent event = (GCEvent) i.next();
StringBuffer sb = new StringBuffer();
event.toStringBuffer(sb);
System.out.println(sb.toString());
}
完整代码
需要gcviewer-x.xx.jar 如:gcviewer-1.29.jar
GCLogToCSV.java
package cn.pl.gclog2csv;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import com.tagtraum.perf.gcviewer.DataReader;
import com.tagtraum.perf.gcviewer.DataReaderFactory;
import com.tagtraum.perf.gcviewer.GCEvent;
import com.tagtraum.perf.gcviewer.GCModel;
public class GCLogToCSV {
private Env env;
private static final DataReaderFactory factory = new DataReaderFactory();
public GCLogToCSV(String[] args) {
env = analyseParameter(args);
}
public void excute() {
if (env == null) {
printUsage();
return;
}
// final GCViewer viewer = new GCViewer();
// viewer.setVisible(false);
InputStream in = null;
PrintWriter heapOut = null;
PrintWriter newOut = null;
PrintWriter oldPermOut = null;
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
try {
heapOut = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(new File(env.getOutputHeapCSV())))));
newOut = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(new File(env.getOutputNewCSV())))));
oldPermOut = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(new File(env.getOutputOldPermCSV())))));
in = new BufferedInputStream(new FileInputStream(new File(env.getInputGCLogPath())));
final DataReader reader = factory.getDataReader(in);
final GCModel model = reader.read();
in.close();
in = null;
writeHeader(heapOut, newOut, oldPermOut);
GCInfo heapInfo = new GCInfo();
GCInfo newInfo = new GCInfo();
GCInfo oldInfo = new GCInfo();
GCInfo permInfo = new GCInfo();
String type;
long offset = 0;
if (env.getStartTime() != null) {
offset = env.getStartTime().getTime();
}
String timpstamp;
boolean getInfoRet;
for (Iterator i = model.getGCEvents(); i.hasNext();) {
GCEvent event = (GCEvent) i.next();
getInfoRet = false;
type = event.getType().toString();
if (offset == 0) {
timpstamp = String.valueOf(event.getTimestamp());
} else {
timpstamp = sdf.format(new Date(offset + (long)(event.getTimestamp() * 1000)));
}
if (GCEvent.Type.GC.toString().equals(type)) {
getInfoRet = getGCInfo(event, newInfo, GCEvent.Type.DEF_NEW.toString());
if (getInfoRet) {
//timestamp,used_newsize,newsize,pausetime
newOut.printf("%s,%s,%s,%s\n",
timpstamp, newInfo.postUsed, newInfo.total, newInfo.pause);
}
getInfoRet = getGCInfo(event, heapInfo, null);
} else if (GCEvent.Type.FULL_GC.toString().equals(type)) {
getInfoRet = getGCInfo(event, oldInfo, GCEvent.Type.TENURED.toString());
if (getInfoRet && getGCInfo(event, permInfo, GCEvent.Type.PERM.toString())) {
//timestamp,used_oldsize,oldsize,old_pausetime,used_termsize,termsize,term_pausetime
oldPermOut.printf("%s,%s,%s,%s,%s,%s,%s\n", timpstamp,
oldInfo.postUsed, oldInfo.total, oldInfo.pause,
permInfo.postUsed, permInfo.total, permInfo.pause);
}
getInfoRet = getGCInfo(event, heapInfo, null);
}
if (getInfoRet) {
//timestamp,used_heapsize,heapsize,pausetime,gc_type
heapOut.printf("%s,%s,%s,%s,%s\n",
timpstamp, heapInfo.postUsed, heapInfo.total, heapInfo.pause, type);
}
//StringBuffer sb = new StringBuffer();
//event.toStringBuffer(sb);
//System.out.println(sb.toString());
}
System.out.println("execute done.");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (heapOut != null) {
heapOut.close();
}
if (newOut != null) {
newOut.close();
}
if (oldPermOut != null) {
oldPermOut.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void writeHeader(PrintWriter heapOut, PrintWriter newOut, PrintWriter oldPermOut) {
heapOut.println("timestamp,used_heapsize,heapsize,pausetime,gc_type");
newOut.println("timestamp,used_newsize,newsize,pausetime");
oldPermOut.println("timestamp,used_oldsize,oldsize,old_pausetime,used_termsize,termsize,term_pausetime");
}
private Env analyseParameter(String[] args) {
Env ret = new Env();
String value;
for (int i = 0; i < args.length; i++) {
if ("-i".equals(args[i])) {
value = getParameterValue(args, ++i);
if (value != null) {
ret.setInputGCLogPath(value);
}
} else if ("-o".equals(args[i])) {
value = getParameterValue(args, ++i);
if (value != null) {
ret.setOutputPath(value);
}
} else if ("-st".equals(args[i])) {
value = getParameterValue(args, ++i);
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
try {
ret.setStartTime(sdf.parse(value));
} catch (ParseException e) {
System.out
.println("Warning: [-st starttime]'s format error. (expect 'yyyy/MM/dd HH:mm:ss')");
}
}
}
}
if (ret.getInputGCLogPath() == null || ret.getOutputPath() == null) {
ret = null;
}
return ret;
}
private String getParameterValue(String[] args, int i) {
String ret = null;
if (i < args.length) {
ret = args[i];
}
return ret;
}
public static void main(String[] args) {
GCLogToCSV gcLogToCSV = new GCLogToCSV(args);
gcLogToCSV.excute();
}
public void printUsage() {
System.out.println("Usage:");
System.out
.println("\tGCLogToCSV -i gclogpath [-o outputcsvpath] [-st starttime(yyyy/MM/dd HH:mm:ss)]");
}
private boolean getGCInfo(GCEvent event, GCInfo gcinfo, String type) {
boolean ret = false;
if (type == null || "".equals(type)) {
gcinfo.postUsed = event.getPostUsed();
gcinfo.total = event.getTotal();
gcinfo.pause = event.getPause();
return true;
}
for (Iterator i = event.details(); i.hasNext();) {
Object o = i.next();
if (o instanceof GCEvent) {
final GCEvent subEvent = (GCEvent)o;
if (subEvent.getType().toString().equals(type)) {
gcinfo.postUsed = subEvent.getPostUsed();
gcinfo.total = subEvent.getTotal();
gcinfo.pause = subEvent.getPause();
ret = true;
break;
}
}
}
return ret;
}
private class GCInfo {
public int postUsed;
public int total;
public double pause;
}
private class Env {
private Date startTime;
private String inputGCLogPath;
private String outputPath;
private String outputNewCSV;
private String outputOldPermCSV;
private String outputHeapCSV;
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public String getInputGCLogPath() {
return inputGCLogPath;
}
public void setInputGCLogPath(String inputGCLogPath) {
this.inputGCLogPath = inputGCLogPath;
if (this.outputPath == null) {
setOutputPath(inputGCLogPath);
}
}
public String getOutputPath() {
return outputPath;
}
public void setOutputPath(String outputPath) {
this.outputPath = outputPath;
this.outputNewCSV = outputPath + "_new.csv";
this.outputOldPermCSV = outputPath + "_old_perm.csv";
this.outputHeapCSV = outputPath + "_heap.csv";
}
public String getOutputNewCSV() {
return outputNewCSV;
}
public String getOutputOldPermCSV() {
return outputOldPermCSV;
}
public String getOutputHeapCSV() {
return outputHeapCSV;
}
}
}