Timings submodule refactoring
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<Thread, ThreadTimings> threadTimings = new ConcurrentHashMap<>();
|
||||
private TimingsFileWriter writer;
|
||||
private TimingsWriter writer;
|
||||
private Thread timingsIoThread;
|
||||
private CountDownLatch ioThreadStopMutex;
|
||||
private BlockingQueue<TimingsRecord> 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<Thread, ThreadTimings> 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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user