package org.ntlab.debuggingControl;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.IntegerValue;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.LongValue;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.StringReference;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
public class SpeedTester {
private static final String TRACE = "org.ntlab.traceCollector.tracer.trace";
private static final String ANALYZER = "org.ntlab.reverseDebugger";
public void countMethodExecutionTest(VirtualMachine vm, ThreadReference thread) {
MethodCaller mc = new MethodCaller(vm, thread);
try {
StringReference threadId = mc.getVm().mirrorOf(String.valueOf(mc.getThreadId()));
ObjectReference threadInstance = (ObjectReference)mc.callStaticMethod(TRACE, "TraceJSON", "getThreadInstance", threadId);
ObjectReference roots = (ObjectReference)mc.setObj(threadInstance).callInstanceMethod("getRoot");
ObjectReference currentMe = (ObjectReference)mc.callInstanceMethod("getCurrentMethodExecution");
String targetSignature = ((StringReference)mc.setObj(currentMe).callInstanceMethod("getSignature")).value();
System.out.println("targetSignature: " + targetSignature);
final int LOOP = 10;
// 一次解析の探索処理を, ReverseDebugger側に作成した場合での処理時間計測
System.out.println(); System.out.println("ReverseDebugger:");
test(mc, roots, targetSignature, SpeedTestType.REVERSE_DEBUGGER, LOOP);
// 一次解析の探索処理を, ターゲットプログラムに埋め込んだTraceCollector側に作成した場合での処理時間計測
System.out.println(); System.out.println("TraceCollector:");
test(mc, roots, targetSignature, SpeedTestType.TRACE_COLLECTOR, LOOP);
} catch (InvalidTypeException | ClassNotLoadedException
| InvocationException | IncompatibleThreadStateException e) {
e.printStackTrace();
}
}
private void test(MethodCaller mc, ObjectReference roots, String targetSignature, SpeedTestType type, final int LOOP)
throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
int count = 0;
long beforeTime = 0, afterTime = 0;
for (int i = 0; i < LOOP; i++) {
mc.setObj(roots);
switch (type) {
case REVERSE_DEBUGGER:
beforeTime = System.nanoTime();
count = countMethodExecutionInReverseDebugger(mc, targetSignature, 0, "--------");
afterTime = System.nanoTime();
break;
case TRACE_COLLECTOR:
beforeTime = System.nanoTime();
count = countMethodExecutionInTraceCollector(mc, targetSignature, 0, "--------");
afterTime = System.nanoTime();
break;
}
System.out.println("Exp " + "(" + type.getTypeName() + ")," + (afterTime - beforeTime));
}
}
private int countMethodExecutionInTraceCollector(MethodCaller mc, String targetSignture, int count, String indent)
throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
VirtualMachine vm = mc.getVm();
String methodName = "countMethodExecutionInTraceCollector";
// return ((IntegerValue)mc.callStaticMethod(TRACE, "TraceJSON", methodName, mc.getObj(),
// vm.mirrorOf(targetSignture), vm.mirrorOf(count), vm.mirrorOf(indent))).value();
return ((IntegerValue)mc.callStaticMethod(ANALYZER, "OnlineTraceAnalyzer", methodName, mc.getObj(),
vm.mirrorOf(targetSignture), vm.mirrorOf(count), vm.mirrorOf(indent))).value();
}
private int countMethodExecutionInReverseDebugger(MethodCaller mc, String targetSignature, int count, String indent)
throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException {
VirtualMachine vm = mc.getVm();
ObjectReference methodExecutions = mc.getObj();
if (methodExecutions == null) {
return count;
}
int methodExecutionsSize = ((IntegerValue)mc.callInstanceMethod("size")).value();
if (methodExecutionsSize == 0) {
return count;
}
for (int i = 0; i < methodExecutionsSize; i++) {
IntegerValue index = vm.mirrorOf(i);
ObjectReference methodExecution = (ObjectReference)mc.setObj(methodExecutions).callInstanceMethod("get", index);
String signature = ((StringReference)mc.setObj(methodExecution).callInstanceMethod("getSignature")).value();
// System.out.println(indent + signature);
if (targetSignature.equals(signature)) {
count++;
}
ObjectReference children = (ObjectReference)mc.callInstanceMethod("getChildren");
count = countMethodExecutionInReverseDebugger(mc.setObj(children), targetSignature, count, indent + "--------");
}
return count;
}
private enum SpeedTestType {
REVERSE_DEBUGGER, TRACE_COLLECTOR;
public String getTypeName() {
switch (this) {
case REVERSE_DEBUGGER:
return "RD";
case TRACE_COLLECTOR:
return "TC";
default:
return "";
}
}
}
}