Newer
Older
org.ntlab.reverseDebugger / org.ntlab.reverseDebugger / src / org / ntlab / debuggingControl / SpeedTester.java
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 "";
			}
		}
	}	
}