diff --git a/event-loop/src/main/java/mc/core/timings/MeasurableThread.java b/event-loop/src/main/java/mc/core/timings/MeasurableThread.java new file mode 100644 index 0000000..9cd2ac3 --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/MeasurableThread.java @@ -0,0 +1,5 @@ +package mc.core.timings; + +public interface MeasurableThread { + ThreadTimings getTimings(); +} diff --git a/event-loop/src/main/java/mc/core/timings/ThreadTimings.java b/event-loop/src/main/java/mc/core/timings/ThreadTimings.java new file mode 100644 index 0000000..f05ad22 --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/ThreadTimings.java @@ -0,0 +1,33 @@ +package mc.core.timings; + +import java.util.Stack; +import java.util.concurrent.atomic.AtomicInteger; + +public class ThreadTimings { + private static AtomicInteger IDS = new AtomicInteger(); + private int threadId; + private Stack stack = new Stack<>(); + + public ThreadTimings() { + this.threadId = IDS.getAndIncrement(); + } + + public int getThreadId() { + return threadId; + } + + public Timings start() { + Timings timings = new Timings(this, stack.size()); + stack.push(timings); + return timings; + } + + public void end(Timings finished) { + Timings timings = null; + while (!stack.isEmpty() && timings != finished) { + timings = stack.pop(); + if (!timings.hasFinished()) + timings.finish(); + } + } +} diff --git a/event-loop/src/main/java/mc/core/timings/Timings.java b/event-loop/src/main/java/mc/core/timings/Timings.java new file mode 100644 index 0000000..8c537cd --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/Timings.java @@ -0,0 +1,51 @@ +package mc.core.timings; + +public class Timings implements AutoCloseable { + private ThreadTimings threadTimings; + private long acquireTime; + @SuppressWarnings("FieldCanBeLocal") + private long endTime = -1; + private int id; + + public Timings(ThreadTimings threadTimings, int id) { + this.id = id; + this.threadTimings = threadTimings; + this.acquireTime = System.nanoTime(); + } + + public static Timings start() { + return TimingsManager.TIMINGS_MANAGER.start(); + } + + public static TimingsManager getTimingsManager() { + return TimingsManager.TIMINGS_MANAGER; + } + + public int getId() { + return id; + } + + public long getEndTime() { + return endTime; + } + + public long getAcquireTime() { + return acquireTime; + } + + public boolean hasFinished() { + return endTime != -1; + } + + public void finish() { + if (hasFinished()) + throw new IllegalStateException("This timing was already finished"); + this.endTime = System.nanoTime(); + } + + @Override + public void close() { + finish(); + this.threadTimings.end(this); + } +} diff --git a/event-loop/src/main/java/mc/core/timings/TimingsManager.java b/event-loop/src/main/java/mc/core/timings/TimingsManager.java new file mode 100644 index 0000000..05a49d5 --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/TimingsManager.java @@ -0,0 +1,19 @@ +package mc.core.timings; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class TimingsManager { + static TimingsManager TIMINGS_MANAGER = new TimingsManager(); + private Map threadTimings = new ConcurrentHashMap<>(); + + public Timings start() { + return getCurrentThreadTimings().start(); + } + + public ThreadTimings getCurrentThreadTimings() { + if (Thread.currentThread() instanceof MeasurableThread) { + return ((MeasurableThread) Thread.currentThread()).getTimings(); + } else return this.threadTimings.computeIfAbsent(Thread.currentThread(), s -> new ThreadTimings()); + } +}