package com.google.code.joto.eventrecorder.writer; import java.io.Serializable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.code.joto.eventrecorder.RecordEventSummary; import com.google.code.joto.eventrecorder.impl.AbstractRecordEventStoreTestHelper; import com.google.code.joto.eventrecorder.impl.CyclicBufferRecordEventStore; import com.google.code.joto.eventrecorder.impl.RollingFileRecordEventStore; import com.google.code.joto.testobj.TestObjFactory; /** * JUnit test for AsyncRecordEventWriter */ public class AsyncRecordEventWriterTest extends AbstractRecordEventStoreTestHelper { private static final Logger log = LoggerFactory.getLogger(AsyncRecordEventWriterTest.class); public AsyncRecordEventWriterTest(String name) { super(name); } public void test1() { CyclicBufferRecordEventStore eventStore = new CyclicBufferRecordEventStore(); AsyncQueueRecordEventWriter writer = new AsyncQueueRecordEventWriter(eventStore.getEventWriter()); int count = 0; assertEquals(1, eventStore.getLastEventId()); count += writeRandomEvents(writer, null, 0, 1); assertEquals(1, eventStore.getLastEventId()); writer.startQueue(); writer.waitEmptyQueue(); assertEquals(1 + count, eventStore.getLastEventId()); count += writeRandomEvents(writer, null, 0, 100); writer.waitEmptyQueue(); assertEquals(1 + count, eventStore.getLastEventId()); writer.stopQueue(); } public void testBenchmarkWriteSimple() { boolean deleteFile = true; // use false for debugging(?): showing file content log.info("benchmark Async+RollingFileRecordEventStore ... First result is not significative because hotspot is lazy..."); String baseName = "AsyncRollingFileRecord"; int maxRollingFiles = 4; int maxFileSize = 1024*1024; // 1Mo doTestBenchmarkWriteSimple(baseName, maxRollingFiles, maxFileSize, 50, 50, deleteFile); log.info("now benchmark with different repeatCount x size"); doTestBenchmarkWriteSimple(baseName, maxRollingFiles, maxFileSize, 1000, 10, deleteFile); doTestBenchmarkWriteSimple(baseName, maxRollingFiles, maxFileSize, 100, 100, deleteFile); // doTestBenchmarkWriteSimple(baseName, maxRollingFiles, maxFileSize, 10, 1000, deleteFile); // doTestBenchmarkWriteSimple(baseName, maxRollingFiles, maxFileSize, 10, 10000); // doTestBenchmarkWriteSimple(baseName, maxRollingFiles, maxFileSize,5, 500000); log.info("benchmark Async+RollingFileRecordEventStore finished"); } protected void doTestBenchmarkWriteSimple( String benchBaseName, int maxRollingFiles, int maxFileSize, final int repeatCount, final int writeCount, boolean deleteFile) { System.gc(); System.gc(); int sizeInMo = maxFileSize / (1024*1024); String fileName = benchBaseName + "_max" + maxRollingFiles + "-" + sizeInMo + "M" + "-bench-x" + repeatCount + "-" + writeCount + ".tmp"; RollingFileRecordEventStore eventStore = setupRollingFileTest(fileName, maxRollingFiles, maxFileSize); try { eventStore.open("rw"); AsyncQueueRecordEventWriter writer = new AsyncQueueRecordEventWriter(eventStore.getEventWriter()); writer.startQueue(); doRunBenchmarkWriteSimple(eventStore, repeatCount, writeCount); writer.waitEmptyQueue(); writer.stopQueue(); writer.waitThreadStopped(); // finish eventStore.close(); } catch(Exception ex) { eventStore.close(); throw new RuntimeException(ex); } finally { if (deleteFile) { eventStore.deleteFiles(); } } } protected RollingFileRecordEventStore setupRollingFileTest( String testFileName, int maxRollingFiles, int maxFileSize) { RollingFileRecordEventStore eventStore = new RollingFileRecordEventStore(getTargetTestDir(), testFileName, ".tmp"); eventStore.setMaxRollingFiles(maxRollingFiles); eventStore.setMaxFileSize(maxFileSize); return eventStore; } protected void tearDownRollingFileTest(RollingFileRecordEventStore rollingFile) { rollingFile.deleteFiles(); } protected void doRunBenchmarkWriteSimple(AsyncQueueRecordEventWriter eventWriter, int repeatCount, int writeCount) { long totalAddNanos = 0; long totalFlushNanos = 0; for (int i = 0; i < repeatCount; i++) { long nanos1 = System.nanoTime(); generateEvents_SimpleIntFieldA(eventWriter, writeCount, 0); long nanos2 = System.nanoTime(); eventWriter.waitEmptyQueue(); long nanos3 = System.nanoTime(); totalAddNanos += (nanos2 - nanos1); totalFlushNanos += (nanos3 - nanos2); // int millis10 = (int) (10*nanos / 1000000); // log.info("write+flush " + writeCount + " events with simple obj, " // + "took:" + (millis10*0.1) + " ms/" + writeCount // + ", " + (millis10*0.1/writeCount) + " ms/u" // ); } log.info("bench Async+RollingFileRecordEventStore: repeat " + repeatCount + " x write+flush " + writeCount + " events with simple obj\n" + " total time: " + formatNanosTotalTime(totalAddNanos + totalFlushNanos, repeatCount, writeCount) + "\n" + " time for addEvent(): " + formatNanosTotalTime(totalAddNanos, repeatCount, writeCount) + "\n" + " time for flush(): " + formatNanosTotalTime(totalFlushNanos, repeatCount, writeCount) + "\n" ); } protected void generateEvents_SimpleIntFieldA(RecordEventWriter eventWriter, int count, int randSeed) { for (int i = 0; i < count; i++) { generateEvent_SimpleIntFieldA(eventWriter, randSeed++); } } protected void generateEvent_SimpleIntFieldA(RecordEventWriter eventWriter, int randSeed) { RecordEventSummary e = RecordEventSummary.snewDefault( "testEventType" + (randSeed%5), "testEventSubType" + (randSeed%10), "testClass" + (randSeed%3), "testMeth" + (randSeed%20)); Serializable objData = TestObjFactory.createSimpleIntFieldA(); eventWriter.addEvent(e, objData, null); } protected String formatNanosTotalTime(long totalNanos, int repeatCount, int size) { int totalMillis = (int) (totalNanos / 1000000); String res = totalMillis + " ms" + ", " + (totalMillis/repeatCount) + " ms/" + size + " in avg" + ", " + ((double)totalMillis/repeatCount/size) + " ms/u in avg"; return res; } protected int writeRandomEvents(RecordEventWriter writer, RecordEventWriterCallback callback, int randSeed, int count) { for (int i = 0; i < count; i++) { writeRandomEvent(writer, callback, randSeed+1); } return count; } protected void writeRandomEvent(RecordEventWriter writer, RecordEventWriterCallback callback, int randSeed) { RecordEventSummary e = RecordEventSummary.snewDefault( "testEventType" + (randSeed%5), "testEventSubType" + (randSeed%10), "testClass" + (randSeed%3), "testMeth" + (randSeed%20)); Serializable objData = TestObjFactory.createAnySerializableBean(randSeed); writer.addEvent(e, objData, callback); } }