From 6bd8b608321d1a08c42d126d6acbd9a2c9aeadde Mon Sep 17 00:00:00 2001 From: Daniil Date: Tue, 7 Aug 2018 16:27:44 +0700 Subject: [PATCH] Timings submodule refactoring --- .../main/java/mc/core/timings/Timings.java | 4 +- .../mc/core/timings/TimingsEventType.java | 17 +++++++++ .../java/mc/core/timings/TimingsManager.java | 37 ++++++++++++++----- .../java/mc/core/timings/TimingsRecord.java | 12 +++--- .../core/timings/TimingsStaticAccessor.java | 9 +++++ .../core/timings/io/DefaultWriterFactory.java | 11 ++++++ .../timings/{ => io}/TimingsFileWriter.java | 23 +++--------- .../mc/core/timings/io/TimingsLogWriter.java | 24 ++++++++++++ .../mc/core/timings/io/TimingsWriter.java | 13 +++++++ .../core/timings/io/TimingsWriterFactory.java | 8 ++++ 10 files changed, 124 insertions(+), 34 deletions(-) create mode 100644 event-loop/src/main/java/mc/core/timings/TimingsEventType.java create mode 100644 event-loop/src/main/java/mc/core/timings/TimingsStaticAccessor.java create mode 100644 event-loop/src/main/java/mc/core/timings/io/DefaultWriterFactory.java rename event-loop/src/main/java/mc/core/timings/{ => io}/TimingsFileWriter.java (76%) create mode 100644 event-loop/src/main/java/mc/core/timings/io/TimingsLogWriter.java create mode 100644 event-loop/src/main/java/mc/core/timings/io/TimingsWriter.java create mode 100644 event-loop/src/main/java/mc/core/timings/io/TimingsWriterFactory.java diff --git a/event-loop/src/main/java/mc/core/timings/Timings.java b/event-loop/src/main/java/mc/core/timings/Timings.java index 3824b3c..b9d1252 100644 --- a/event-loop/src/main/java/mc/core/timings/Timings.java +++ b/event-loop/src/main/java/mc/core/timings/Timings.java @@ -14,11 +14,11 @@ public class Timings implements AutoCloseable { } public static Timings start() { - return TimingsManager.TIMINGS_MANAGER.getCurrentThreadTimings().start(); + return TimingsStaticAccessor.getTimingsManager().getCurrentThreadTimings().start(); } public static TimingsManager getTimingsManager() { - return TimingsManager.TIMINGS_MANAGER; + return TimingsStaticAccessor.getTimingsManager(); } public int getId() { diff --git a/event-loop/src/main/java/mc/core/timings/TimingsEventType.java b/event-loop/src/main/java/mc/core/timings/TimingsEventType.java new file mode 100644 index 0000000..181643a --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/TimingsEventType.java @@ -0,0 +1,17 @@ +package mc.core.timings; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum TimingsEventType { + TIMINGS_START((short) 0), + TIMINGS_END((short) 1), + TIMINGS_FILE_INITIALIZING((short) 2), + TIMINGS_FILE_INITIALIZED((short) 3), + TIMINGS_CHANGE_THREAD_OPTIONS((short) 4), + TIMINGS_FILE_END((short) 5); + + @Getter + private final short id; +} \ No newline at end of file diff --git a/event-loop/src/main/java/mc/core/timings/TimingsManager.java b/event-loop/src/main/java/mc/core/timings/TimingsManager.java index 77e36a0..07ac32a 100644 --- a/event-loop/src/main/java/mc/core/timings/TimingsManager.java +++ b/event-loop/src/main/java/mc/core/timings/TimingsManager.java @@ -1,6 +1,11 @@ package mc.core.timings; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import mc.core.timings.io.DefaultWriterFactory; +import mc.core.timings.io.TimingsWriter; +import mc.core.timings.io.TimingsWriterFactory; +import org.springframework.beans.factory.annotation.Autowired; import java.io.File; import java.io.IOException; @@ -14,30 +19,38 @@ import java.util.concurrent.locks.ReentrantLock; @Slf4j public class TimingsManager { - static TimingsManager TIMINGS_MANAGER = new TimingsManager(); + // These variables are essential in Timings thread synchronization private final AtomicBoolean waitForFile = new AtomicBoolean(false); private Map threadTimings = new ConcurrentHashMap<>(); - private TimingsFileWriter writer; + private TimingsWriter writer; private Thread timingsIoThread; private CountDownLatch ioThreadStopMutex; private BlockingQueue queue; private ReentrantLock queueAccessLock = new ReentrantLock(); + // For modularity purposes + @Autowired + @Setter + private TimingsWriterFactory writerFactory = new DefaultWriterFactory(); + + public TimingsManager() { + TimingsStaticAccessor.TIMINGS_MANAGER = this; + } public void startRecording(File file) { synchronized (waitForFile) { waitForFile.set(true); } try { - writer = new TimingsFileWriter(file); - writer.writeEvent(0, 0, System.nanoTime(), TimingsFileWriter.TimingsEventType.TIMINGS_FILE_INITIALIZING); + writer = writerFactory.newInstance(file); + writer.writeEvent(0, 0, System.nanoTime(), TimingsEventType.TIMINGS_FILE_INITIALIZING); // Synchronize current thread state for (Map.Entry pair : threadTimings.entrySet()) { - writer.writeEvent(pair.getValue().getThreadId(), 0, System.nanoTime(), TimingsFileWriter.TimingsEventType.TIMINGS_CHANGE_THREAD_OPTIONS, "name: " + pair.getKey().getName()); + writer.writeEvent(pair.getValue().getThreadId(), 0, System.nanoTime(), TimingsEventType.TIMINGS_CHANGE_THREAD_OPTIONS, "name: " + pair.getKey().getName()); for (Timings timings : pair.getValue().getStack()) { - writer.writeEvent(pair.getValue().getThreadId(), timings.getId(), timings.getAcquireTime(), TimingsFileWriter.TimingsEventType.TIMINGS_START); + writer.writeEvent(pair.getValue().getThreadId(), timings.getId(), timings.getAcquireTime(), TimingsEventType.TIMINGS_START); } } - writer.writeEvent(0, 0, System.nanoTime(), TimingsFileWriter.TimingsEventType.TIMINGS_FILE_INITIALIZED); + writer.writeEvent(0, 0, System.nanoTime(), TimingsEventType.TIMINGS_FILE_INITIALIZED); queue = new ArrayBlockingQueue<>(200); ioThreadStopMutex = new CountDownLatch(1); timingsIoThread = new Thread() { @@ -47,6 +60,8 @@ public class TimingsManager { while (!isInterrupted() && isAlive()) { TimingsRecord record; try { + if (queue == null) + return; record = queue.take(); } catch (InterruptedException e) { return; @@ -58,7 +73,9 @@ public class TimingsManager { } } }; - } catch (IOException e) { + timingsIoThread.setName("Timings IO thread"); + timingsIoThread.start(); + } catch (Exception e) { log.error("Unable to start timings recording", e); } synchronized (waitForFile) { @@ -80,7 +97,7 @@ public class TimingsManager { log.error("Unable to wait until last record would be written to file", e); } // Write EOF event - writer.writeEvent(0, 0, System.nanoTime(), TimingsFileWriter.TimingsEventType.TIMINGS_FILE_END); + writer.writeEvent(0, 0, System.nanoTime(), TimingsEventType.TIMINGS_FILE_END); // Unload file try { writer.close(); @@ -100,7 +117,7 @@ public class TimingsManager { new TimingsRecord(thread.getThreadId(), timings.getId(), start ? timings.getAcquireTime() : timings.getEndTime(), - start ? TimingsFileWriter.TimingsEventType.TIMINGS_START : TimingsFileWriter.TimingsEventType.TIMINGS_END + start ? TimingsEventType.TIMINGS_START : TimingsEventType.TIMINGS_END ) ); } finally { diff --git a/event-loop/src/main/java/mc/core/timings/TimingsRecord.java b/event-loop/src/main/java/mc/core/timings/TimingsRecord.java index 38eef49..3d3e3f6 100644 --- a/event-loop/src/main/java/mc/core/timings/TimingsRecord.java +++ b/event-loop/src/main/java/mc/core/timings/TimingsRecord.java @@ -1,20 +1,22 @@ package mc.core.timings; -public class TimingsRecord { +import mc.core.timings.io.TimingsWriter; + +class TimingsRecord { private int threadId; private int stackId; private long time; - private TimingsFileWriter.TimingsEventType eventType; + private TimingsEventType eventType; private String data; - public TimingsRecord(int threadId, int stackId, long time, TimingsFileWriter.TimingsEventType eventType) { + public TimingsRecord(int threadId, int stackId, long time, TimingsEventType eventType) { this.threadId = threadId; this.stackId = stackId; this.time = time; this.eventType = eventType; } - public TimingsRecord(int threadId, int stackId, long time, TimingsFileWriter.TimingsEventType eventType, String data) { + public TimingsRecord(int threadId, int stackId, long time, TimingsEventType eventType, String data) { this.threadId = threadId; this.stackId = stackId; this.time = time; @@ -22,7 +24,7 @@ public class TimingsRecord { this.data = data; } - public void writeToFile(TimingsFileWriter fileWriter) { + public void writeToFile(TimingsWriter fileWriter) { if (data == null) fileWriter.writeEvent(threadId, stackId, time, eventType); else diff --git a/event-loop/src/main/java/mc/core/timings/TimingsStaticAccessor.java b/event-loop/src/main/java/mc/core/timings/TimingsStaticAccessor.java new file mode 100644 index 0000000..35d0ed4 --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/TimingsStaticAccessor.java @@ -0,0 +1,9 @@ +package mc.core.timings; + +public class TimingsStaticAccessor { + static TimingsManager TIMINGS_MANAGER; + + public static TimingsManager getTimingsManager() { + return TIMINGS_MANAGER != null ? TIMINGS_MANAGER : (TIMINGS_MANAGER = new TimingsManager()); + } +} diff --git a/event-loop/src/main/java/mc/core/timings/io/DefaultWriterFactory.java b/event-loop/src/main/java/mc/core/timings/io/DefaultWriterFactory.java new file mode 100644 index 0000000..192ee03 --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/io/DefaultWriterFactory.java @@ -0,0 +1,11 @@ +package mc.core.timings.io; + +import java.io.File; +import java.io.IOException; + +public class DefaultWriterFactory implements TimingsWriterFactory { + @Override + public TimingsWriter newInstance(File file) throws IOException { + return new TimingsFileWriter(file); + } +} diff --git a/event-loop/src/main/java/mc/core/timings/TimingsFileWriter.java b/event-loop/src/main/java/mc/core/timings/io/TimingsFileWriter.java similarity index 76% rename from event-loop/src/main/java/mc/core/timings/TimingsFileWriter.java rename to event-loop/src/main/java/mc/core/timings/io/TimingsFileWriter.java index 451fb88..f7bf92c 100644 --- a/event-loop/src/main/java/mc/core/timings/TimingsFileWriter.java +++ b/event-loop/src/main/java/mc/core/timings/io/TimingsFileWriter.java @@ -1,9 +1,8 @@ -package mc.core.timings; +package mc.core.timings.io; -import lombok.Getter; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import mc.core.timings.TimingsEventType; import java.io.File; import java.io.FileOutputStream; @@ -13,7 +12,7 @@ import java.util.concurrent.locks.ReentrantLock; @SuppressWarnings("Duplicates") @Slf4j -public class TimingsFileWriter { +public class TimingsFileWriter implements TimingsWriter { private FileOutputStream fileOutputStream; private ObjectOutputStream writer; private ReentrantLock lock = new ReentrantLock(); @@ -23,6 +22,7 @@ public class TimingsFileWriter { writer = new ObjectOutputStream(fileOutputStream); } + @Override public void writeEvent(int threadId, int stackId, long time, TimingsEventType type) { lock.lock(); try { @@ -37,6 +37,7 @@ public class TimingsFileWriter { } } + @Override public void writeEvent(int threadId, int stackId, long time, TimingsEventType type, String data) { lock.lock(); try { @@ -52,21 +53,9 @@ public class TimingsFileWriter { } } + @Override public void close() throws IOException { writer.close(); fileOutputStream.close(); } - - @RequiredArgsConstructor - public enum TimingsEventType { - TIMINGS_START((short) 0), - TIMINGS_END((short) 1), - TIMINGS_FILE_INITIALIZING((short) 2), - TIMINGS_FILE_INITIALIZED((short) 3), - TIMINGS_CHANGE_THREAD_OPTIONS((short) 4), - TIMINGS_FILE_END((short) 5); - - @Getter - private final short id; - } } diff --git a/event-loop/src/main/java/mc/core/timings/io/TimingsLogWriter.java b/event-loop/src/main/java/mc/core/timings/io/TimingsLogWriter.java new file mode 100644 index 0000000..0fa5fa3 --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/io/TimingsLogWriter.java @@ -0,0 +1,24 @@ +package mc.core.timings.io; + +import lombok.extern.slf4j.Slf4j; +import mc.core.timings.TimingsEventType; + +import java.io.IOException; + +@Slf4j +public class TimingsLogWriter implements TimingsWriter { + @Override + public void writeEvent(int threadId, int stackId, long time, TimingsEventType type) { + log.info("[{}] Thread #{}, Stack #{}: {}", time, threadId, stackId, type.toString()); + } + + @Override + public void writeEvent(int threadId, int stackId, long time, TimingsEventType type, String data) { + log.info("[{}] Thread #{}, Stack #{}: {} ({})", time, threadId, stackId, type.toString(), data); + } + + @Override + public void close() throws IOException { + + } +} diff --git a/event-loop/src/main/java/mc/core/timings/io/TimingsWriter.java b/event-loop/src/main/java/mc/core/timings/io/TimingsWriter.java new file mode 100644 index 0000000..640bdd5 --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/io/TimingsWriter.java @@ -0,0 +1,13 @@ +package mc.core.timings.io; + +import mc.core.timings.TimingsEventType; + +import java.io.IOException; + +public interface TimingsWriter { + void writeEvent(int threadId, int stackId, long time, TimingsEventType type); + + void writeEvent(int threadId, int stackId, long time, TimingsEventType type, String data); + + void close() throws IOException; +} diff --git a/event-loop/src/main/java/mc/core/timings/io/TimingsWriterFactory.java b/event-loop/src/main/java/mc/core/timings/io/TimingsWriterFactory.java new file mode 100644 index 0000000..db12e6a --- /dev/null +++ b/event-loop/src/main/java/mc/core/timings/io/TimingsWriterFactory.java @@ -0,0 +1,8 @@ +package mc.core.timings.io; + +import java.io.File; +import java.io.IOException; + +public interface TimingsWriterFactory { + TimingsWriter newInstance(File file) throws IOException; +}