package se.krka.kahlua.profiler; import se.krka.kahlua.vm.*; import java.util.TimerTask; import java.util.Timer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class Sampler { private static final AtomicInteger NEXT_ID = new AtomicInteger(); private final LuaState state; private final Timer timer; private final long period; private final Profiler profiler; public Sampler(LuaState state, long period, Profiler profiler) { this.state = state; this.period = period; this.profiler = profiler; timer = new Timer("Kahlua Sampler-" + NEXT_ID.incrementAndGet(), true); } public void start() { TimerTask timerTask = new TimerTask() { @Override public void run() { List<StacktraceElement> list = new ArrayList<StacktraceElement>(); appendList(list, state.currentThread); profiler.getSample(new Sample(list, period)); } }; timer.scheduleAtFixedRate(timerTask, 0, period); } private void appendList(List<StacktraceElement> list, LuaThread thread) { while (thread != null) { int top = thread.callFrameTop; for (int i = top - 1; i >= 0; i--) { LuaCallFrame frame = thread.callFrameStack[i]; int pc = frame.pc - 1; LuaClosure closure = frame.closure; JavaFunction javaFunction = frame.javaFunction; if (closure != null) { list.add(new LuaStacktraceElement(pc, closure.prototype)); } else if (javaFunction != null) { list.add(new JavaStacktraceElement(javaFunction)); } } thread = thread.parent; } } public void stop() { timer.cancel(); } }