package ch.usi.inf.sp.dbi.profiler; import java.util.ArrayDeque; import java.util.Collections; import java.util.Deque; public class Profiler { private static final CCTNode rootNode = new CCTNode(RootFrame.INSTANCE); private static final Deque callStack = new ArrayDeque<>(Collections.singletonList(rootNode)); static { Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.out.println("\nCalling Context Tree:"); System.out.println(rootNode); })); } private static String indent(int n) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; i++) { sb.append(" "); } return sb.toString(); } public static void entry(String clazz, String method, String desc) { final CCTNode parent = callStack.getFirst(); final Frame frame = new Frame(clazz, method, desc); callStack.push(parent.getOrAddChild(frame)); // System.out.println("profiler captured: > " + indent(callStack.size()) + callStack.getFirst().getFrame().getName()); } public static void exit(String clazz, String method, String desc) { final Frame exitingFrom = new Frame(clazz, method, desc); final IFrame lastCalled = callStack.isEmpty() ? null : callStack.getFirst().getFrame(); if (!exitingFrom.equals(lastCalled)) { throw new IllegalStateException("Expecting to exit from " + lastCalled + ", but found " + exitingFrom); } // System.out.println("profiler captured: < " + indent(callStack.size()) + callStack.getFirst().getFrame().getName()); callStack.pop(); } }