Archived
0

Timings submodule refactoring

This commit is contained in:
Daniil
2018-08-07 16:27:44 +07:00
parent 22dbf8caa8
commit 6bd8b60832
10 changed files with 124 additions and 34 deletions

View File

@@ -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() {

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View 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;
}
}

View File

@@ -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 {
}
}

View File

@@ -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;
}

View File

@@ -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;
}