Skip to content

Commit

Permalink
performance tuning
Browse files Browse the repository at this point in the history
  • Loading branch information
dkarv committed Jan 29, 2018
1 parent 97d748e commit a1cdd69
Show file tree
Hide file tree
Showing 32 changed files with 159 additions and 1,615 deletions.
17 changes: 7 additions & 10 deletions jdcallgraph/src/main/java/com/dkarv/jdcallgraph/CallRecorder.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,24 @@
public class CallRecorder {
private static final Logger LOG = new Logger(CallRecorder.class);

public static void beforeMethod(String className, String methodName, int lineNumber,
boolean isTest) {
public static void beforeMethod(String method, boolean isTest) {
try {
if (isTest) {
LOG.info("* Starting {}::{}", className, methodName);
LOG.info("* Starting {}", method);
}
StackItem item = StackItemCache.get(className, methodName, lineNumber, isTest);
CallQueue.add(new CallTask(item, Thread.currentThread().getId(), true));
// StackItem item = StackItemCache.get(className, methodName, lineNumber, isTest);
CallQueue.add(new CallTask(method, Thread.currentThread().getId(), true));
} catch (Throwable e) {
LOG.error("Error in beforeMethod", e);
}
}

public static void afterMethod(String className, String methodName, int lineNumber,
boolean isTest) {
public static void afterMethod(String method, boolean isTest) {
try {
if (isTest) {
LOG.info("* Finished {}::{}", className, methodName);
LOG.info("* Finished {}", method);
}
StackItem item = StackItemCache.get(className, methodName, lineNumber, isTest);
CallQueue.add(new CallTask(item, Thread.currentThread().getId(), false));
CallQueue.add(new CallTask(method, Thread.currentThread().getId(), false));
} catch (Throwable e) {
LOG.error("Error in afterMethod", e);
}
Expand Down
28 changes: 19 additions & 9 deletions jdcallgraph/src/main/java/com/dkarv/jdcallgraph/Tracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.dkarv.jdcallgraph.util.config.Config;
import com.dkarv.jdcallgraph.util.log.Logger;
import com.dkarv.jdcallgraph.util.config.ConfigReader;
import com.dkarv.jdcallgraph.util.options.Formatter;
import com.dkarv.jdcallgraph.worker.CallQueue;
import javassist.*;
import javassist.bytecode.*;
Expand All @@ -47,6 +48,7 @@
*/
public class Tracer implements ClassFileTransformer {
private final static Logger LOG = new Logger(Tracer.class);
private static final String TARGET = CallRecorder.class.getCanonicalName();
private final List<Pattern> excludes;

private final FieldTracer fieldTracer = new FieldTracer();
Expand Down Expand Up @@ -201,20 +203,28 @@ void enhanceMethod(CtBehavior method, String className)

int lineNumber = getLineNumber(method);

String args;
StringBuilder srcBefore = new StringBuilder(TARGET);
srcBefore.append(".beforeMethod(");
StringBuilder srcAfter = new StringBuilder(TARGET);
srcAfter.append(".afterMethod(");

if (isTest) {
LOG.debug("subtest detection enabled on {}::{}", className, mName);
args =
"getClass().getCanonicalName()" + ',' + '"' + mName + '"' + ',' + lineNumber + ',' + true;
srcBefore.append(Formatter.class.getCanonicalName()).append(".formatTest(")
.append("getClass().getCanonicalName(),\"").append(mName).append("\",").append(lineNumber)
.append(",true);");
srcAfter.append(Formatter.class.getCanonicalName()).append(".format(")
.append("getClass().getCanonicalName(),\"").append(mName).append("\",").append(lineNumber)
.append(",true);");
} else {
args = '"' + className + '"' + ',' + '"' + mName + '"' + ',' + lineNumber + ',' + false;
srcBefore.append('"').append(Formatter.format(className, mName, lineNumber))
.append("\",false);");
srcAfter.append('"').append(Formatter.format(className, mName, lineNumber))
.append("\",false);");
}

String srcBefore = "com.dkarv.jdcallgraph.CallRecorder.beforeMethod(" + args + ");";
String srcAfter = "com.dkarv.jdcallgraph.CallRecorder.afterMethod(" + args + ");";

method.insertBefore(srcBefore);
method.insertAfter(srcAfter, true);
method.insertBefore(srcBefore.toString());
method.insertAfter(srcAfter.toString(), true);
//if (isConstructor) {
// CtClass etype = ClassPool.getDefault().get("java.lang.Exception");
// method.addCatch("{ " + srcAfter + " throw $e; }", etype);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ public class CallGraph {
private static final Logger LOG = new Logger(CallGraph.class);
private static final String FOLDER = "cg/";
private final long threadId;
final Stack<StackItem> calls = new Stack<>();
final Stack<Integer> reads = new Stack<>();
final Stack<String> calls = new Stack<>();

final List<GraphWriter> writers = new ArrayList<>();

Expand Down Expand Up @@ -79,19 +78,18 @@ static GraphWriter createWriter(Target t, boolean multiGraph) {
* @param method called method
* @return identifier if method is a valid start condition, null otherwise
*/
String checkStartCondition(StackItem method) {
String checkStartCondition(String method) {
switch (Config.getInst().groupBy()) {
case THREAD:
return FOLDER + String.valueOf(threadId);
case ENTRY:
return FOLDER + method.toString();
return FOLDER + method;
default:
throw new IllegalArgumentException("Unknown groupBy: " + Config.getInst().groupBy());
}
}

public void called(StackItem method) throws IOException {
reads.push(0);
public void called(String method) throws IOException {
if (calls.isEmpty()) {
// First node
String identifier = checkStartCondition(method);
Expand All @@ -113,42 +111,35 @@ public void called(StackItem method) throws IOException {
}
}

public void returned(StackItem method) throws IOException {
//if (!reads.isEmpty()) {
// int r = reads.pop();
// if (r != 0) {
// LOG.info("{} did reads: {}", method, r);
// }
//}
Stack<StackItem> trace = new Stack<>();
int removed = 0;
boolean found = false;
while (!calls.isEmpty() && !found) {
removed++;
StackItem topItem = calls.pop();
trace.push(topItem);
if (topItem.equals(method)) {
found = true;
public void returned(String method) throws IOException {
if (!method.equals(calls.pop())) {
Stack<String> trace = new Stack<>();
int removed = 1;
boolean found = false;
while (!calls.isEmpty() && !found) {
removed++;
String topItem = calls.pop();
trace.push(topItem);
if (topItem.equals(method)) {
found = true;
}
}
}
if (removed != 1) {
LOG.warn("Error when method {} returned:", method);
LOG.warn("Removed {} entries. Stack trace {}", removed, trace);
}
if (!found) {
LOG.warn("Couldn't find the returned method call on stack");
LOG.warn("Removed {} entries. Stack trace (top element missing) {}", removed, trace);
if (!found) {
LOG.error("Couldn't find the returned method call on stack");
}
}

if (calls.isEmpty()) {
for (GraphWriter w : writers) {
w.end();
}
}
}

/*
public void dataEdge(StackItem from, StackItem to) throws IOException {
if (!reads.isEmpty()) {
reads.push(reads.pop() + 1);
}
if (calls.isEmpty()) {
LOG.info("Ignore dd egde {} -> {}", from, to);
} else {
Expand All @@ -158,7 +149,7 @@ public void dataEdge(StackItem from, StackItem to) throws IOException {
}
}
}
}
}*/

public void finish() throws IOException {
if (!calls.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class DataDependenceGraph {
private static final String FOLDER = "ddg/";
final List<GraphWriter> writers = new ArrayList<>();

private Map<String, StackItem> lastWrites = new ConcurrentHashMap<>();
private Map<String, String> lastWrites = new ConcurrentHashMap<>();

public DataDependenceGraph() throws IOException {
Target[] targets = Config.getInst().writeTo();
Expand All @@ -69,17 +69,17 @@ private GraphWriter createWriter(Target target) {
}
}

public void addWrite(StackItem location, String field) throws IOException {
public void addWrite(String location, String field) throws IOException {
LOG.trace("Write to {} from {}", field, location);
StackItem item = this.lastWrites.get(field);
String item = this.lastWrites.get(field);
if (!location.equals(item)) {
this.lastWrites.put(field, location);
}
}

public void addRead(StackItem location, String field, CallGraph callGraph) throws IOException {
public void addRead(String location, String field, CallGraph callGraph) throws IOException {
LOG.trace("Read to {} from {}", field, location);
StackItem lastWrite = lastWrites.get(field);
String lastWrite = lastWrites.get(field);
if (lastWrite != null) {
if (!lastWrite.equals(location)) {
// ignore dependency on itself
Expand All @@ -88,9 +88,9 @@ public void addRead(StackItem location, String field, CallGraph callGraph) throw
writer.edge(lastWrite, location);
// writer.edge(lastWrite, location, "[label=\"" + field + "\"]");
}
if (callGraph != null) {
callGraph.dataEdge(lastWrite, location);
}
//if (callGraph != null) {
// callGraph.dataEdge(lastWrite, location);
//}
}
}
}
Expand Down
36 changes: 26 additions & 10 deletions jdcallgraph/src/main/java/com/dkarv/jdcallgraph/util/StackItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public StackItem(String className, String methodName, int lineNumber, boolean te

this.test = test;

this.formatted = Formatter.format(this);
this.formatted = Formatter.format(className, methodName, lineNumber);
}

StackItem(String className, String methodName, int lineNumber) {
Expand Down Expand Up @@ -91,23 +91,39 @@ public boolean equals(Object other) {
}

public String getPackageName() {
int indexDot = className.lastIndexOf('.');
return className.substring(0, indexDot);
return StackItem.getPackageName(className);
}

public String getShortClassName() {
int indexDot = className.lastIndexOf('.');
return className.substring(indexDot + 1);
return StackItem.getShortClassName(className);
}

public String getShortMethodName() {
int indexBracket = methodName.indexOf('(');
return methodName.substring(0, indexBracket);
return StackItem.getShortMethodName(methodName);
}

public String getMethodParameters() {
int openBracket = methodName.indexOf('(');
int closingBracket = methodName.indexOf(')');
return methodName.substring(openBracket + 1, closingBracket);
return StackItem.getMethodParameters(methodName);
}

public static String getPackageName(String type) {
int indexDot = type.lastIndexOf('.');
return type.substring(0, indexDot);
}

public static String getShortClassName(String type) {
int indexDot = type.lastIndexOf('.');
return type.substring(indexDot + 1);
}

public static String getShortMethodName(String method) {
int indexBracket = method.indexOf('(');
return method.substring(0, indexBracket);
}

public static String getMethodParameters(String method) {
int openBracket = method.indexOf('(');
int closingBracket = method.indexOf(')');
return method.substring(openBracket + 1, closingBracket);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,39 @@ public class Formatter {
private static final Logger LOG = new Logger(Formatter.class);
private static final Pattern P = Pattern.compile("\\{(.+?)}");

public static String format(StackItem item) {
public static String formatTest(String type, String method, int lineNumber) {
return type + "::" + StackItem.getShortMethodName(method) + "#" + lineNumber;
}

public static String format(String type, String method, int lineNumber) {
return type + "#" + lineNumber;
/*
Matcher m = P.matcher(Config.getInst().format());
StringBuffer result = new StringBuffer();
while (m.find()) {
String replacement = replace(m.group(1), item);
String replacement = replace(m.group(1), type, method, lineNumber);
replacement = Matcher.quoteReplacement(replacement);
m.appendReplacement(result, replacement);
}
return result.toString();
return result.toString();*/
}

public static String replace(String id, StackItem item) {
public static String replace(String id, String type, String method, int lineNumber) {
switch (id) {
case "package":
return item.getPackageName();
return StackItem.getPackageName(type);
case "class":
return item.getClassName();
return type;
case "classname":
return item.getShortClassName();
return StackItem.getShortClassName(type);
case "line":
return Integer.toString(item.getLineNumber());
return Integer.toString(lineNumber);
case "method":
return item.getMethodName();
return method;
case "methodname":
return item.getShortMethodName();
return StackItem.getShortMethodName(method);
case "parameters":
return item.getMethodParameters();
return StackItem.getMethodParameters(method);
default:
LOG.error("Unknown pattern: {}", id);
// Unknown pattern, return without modification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
package com.dkarv.jdcallgraph.worker;

import com.dkarv.jdcallgraph.util.log.Logger;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class CallQueue {
private static final Logger LOG = new Logger(CallQueue.class);
private static final BlockingQueue<CallTask> QUEUE = new LinkedBlockingQueue<>(1000);
private static final BlockingQueue<CallTask> QUEUE = new ArrayBlockingQueue<>(1000);

public static void add(CallTask task) {
try {
Expand Down
Loading

0 comments on commit a1cdd69

Please sign in to comment.