package com.ldbc.driver.runtime; import com.ldbc.driver.Operation; import com.ldbc.driver.SerializingMarshallingException; import com.ldbc.driver.Workload; import com.ldbc.driver.WorkloadException; import com.ldbc.driver.WorkloadStreams; import com.ldbc.driver.control.ConsoleAndFileDriverConfiguration; import com.ldbc.driver.control.DriverConfiguration; import com.ldbc.driver.control.DriverConfigurationException; import com.ldbc.driver.control.Log4jLoggingServiceFactory; import com.ldbc.driver.control.LoggingServiceFactory; import com.ldbc.driver.generator.GeneratorFactory; import com.ldbc.driver.generator.RandomDataGeneratorFactory; import com.ldbc.driver.temporal.SystemTimeSource; import com.ldbc.driver.temporal.TimeSource; import com.ldbc.driver.testutils.TestUtils; import com.ldbc.driver.util.Tuple3; import com.ldbc.driver.workloads.ldbc.snb.interactive.LdbcSnbInteractiveWorkload; import com.ldbc.driver.workloads.ldbc.snb.interactive.LdbcSnbInteractiveWorkloadConfiguration; import com.ldbc.driver.workloads.ldbc.snb.interactive.db.DummyLdbcSnbInteractiveDb; import org.junit.Ignore; import org.junit.Test; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; import static java.lang.String.format; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; @Ignore public class QueuePerformanceTests { final Operation TERMINATE_OPERATION = new Operation<Object>() { @Override public int type() { return -1; } @Override public Object marshalResult( String serializedOperationResult ) throws SerializingMarshallingException { return null; } @Override public String serializeResult( Object operationResultInstance ) throws SerializingMarshallingException { return null; } }; final Integer TERMINATE = -1; final TimeSource timeSource = new SystemTimeSource(); @Test public void operationQueuePerformanceTest() throws WorkloadException, InterruptedException, IOException, DriverConfigurationException { // Given Map<String,String> paramsMap = LdbcSnbInteractiveWorkloadConfiguration.defaultReadOnlyConfigSF1(); paramsMap.put( LdbcSnbInteractiveWorkloadConfiguration.PARAMETERS_DIRECTORY, TestUtils.getResource( "/" ).getAbsolutePath() ); // LDBC Interactive Workload-specific parameters // Driver-specific parameters String name = null; String dbClassName = DummyLdbcSnbInteractiveDb.class.getName(); String workloadClassName = LdbcSnbInteractiveWorkload.class.getName(); long operationCount = 10000000; int threadCount = 1; int statusDisplayInterval = 0; TimeUnit timeUnit = TimeUnit.MILLISECONDS; String resultDirPath = null; double timeCompressionRatio = 1.0; Set<String> peerIds = new HashSet<>(); ConsoleAndFileDriverConfiguration.ConsoleAndFileValidationParamOptions validationParams = null; String dbValidationFilePath = null; boolean calculateWorkloadStatistics = false; long spinnerSleepDuration = 0l; boolean printHelp = false; boolean ignoreScheduledStartTimes = false; long warmupCount = 0; long skipCount = 0; DriverConfiguration config = new ConsoleAndFileDriverConfiguration( paramsMap, name, dbClassName, workloadClassName, operationCount, threadCount, statusDisplayInterval, timeUnit, resultDirPath, timeCompressionRatio, peerIds, validationParams, dbValidationFilePath, calculateWorkloadStatistics, spinnerSleepDuration, printHelp, ignoreScheduledStartTimes, warmupCount, skipCount ); GeneratorFactory gf = new GeneratorFactory( new RandomDataGeneratorFactory( 42L ) ); boolean returnStreamsWithDbConnector = false; LoggingServiceFactory loggingServiceFactory = new Log4jLoggingServiceFactory( false ); Tuple3<WorkloadStreams,Workload,Long> workloadStreamsAndWorkload = WorkloadStreams.createNewWorkloadWithOffsetAndLimitedWorkloadStreams( config, gf, returnStreamsWithDbConnector, 0, config.operationCount(), loggingServiceFactory ); WorkloadStreams workloadStreams = workloadStreamsAndWorkload._1(); Workload workload = workloadStreamsAndWorkload._2(); Iterator<Operation> operations = WorkloadStreams.mergeSortedByStartTimeExcludingChildOperationGenerators( gf, workloadStreams ); System.out.println( "Benchmarking..." ); // long duration = doOperationQueuePerformanceTest(operations, DefaultQueues.<Operation>newBlockingBounded // (1000)); long duration = doOperationQueuePerformanceTest( operations, DefaultQueues.<Operation>newBlockingBounded( 10000 ) ); long opsPerSecond = Math.round( ((double) config.operationCount() / TimeUnit.MILLISECONDS.toNanos( duration )) * 1000000000 ); System.out.println( format( "%s operations in %s: %s op/sec", config.operationCount(), duration, opsPerSecond ) ); workload.close(); } private long doOperationQueuePerformanceTest( final Iterator<Operation> operations, final Queue<Operation> queue ) throws InterruptedException { final QueueEventSubmitter<Operation> queueEventSubmitter = QueueEventSubmitter.queueEventSubmitterFor( queue ); final QueueEventFetcher<Operation> queueEventFetcher = QueueEventFetcher.queueEventFetcherFor( queue ); Thread writeThread = new Thread() { @Override public void run() { while ( operations.hasNext() ) { try { queueEventSubmitter.submitEventToQueue( operations.next() ); } catch ( InterruptedException e ) { e.printStackTrace(); } } try { queueEventSubmitter.submitEventToQueue( TERMINATE_OPERATION ); } catch ( InterruptedException e ) { e.printStackTrace(); } System.out.println( "Producer finished" ); } }; Thread readThread = new Thread() { @Override public void run() { Operation operation = null; try { operation = queueEventFetcher.fetchNextEvent(); } catch ( InterruptedException e ) { e.printStackTrace(); } while ( TERMINATE_OPERATION != operation ) { try { operation = queueEventFetcher.fetchNextEvent(); } catch ( InterruptedException e ) { e.printStackTrace(); } } System.out.println( "Consumer finished" ); } }; long startTime = timeSource.nowAsMilli(); readThread.start(); writeThread.start(); writeThread.join(); readThread.join(); return timeSource.nowAsMilli() - startTime; } @Ignore @Test public void comparePerformanceOfQueueImplementationsDuringConcurrentAccess() throws InterruptedException { int queueItemCount = 1000000; int experimentCount = 5; long totalDurationConcurrentLinkedQueueNonBlocking = 0l; long totalDurationLinkedBlockingQueueNonBlocking = 0l; long totalDurationLinkedBlockingQueueBlocking = 0l; long totalDurationArrayBlockingQueueNonBlocking = 0l; long totalDurationArrayBlockingQueueBlocking = 0l; long totalDurationLinkedTransferQueueAddPollNonBlocking = 0l; long totalDurationLinkedTransferQueuePutTakeBlocking = 0l; long totalDurationSynchronousQueueBlocking = 0l; for ( int i = 0; i < experimentCount; i++ ) { totalDurationConcurrentLinkedQueueNonBlocking = totalDurationConcurrentLinkedQueueNonBlocking + nonBlockingQueuePerformanceTest( queueItemCount, new ConcurrentLinkedQueue<Integer>() ); totalDurationLinkedBlockingQueueNonBlocking = totalDurationLinkedBlockingQueueNonBlocking + nonBlockingQueuePerformanceTest( queueItemCount, new LinkedBlockingQueue<Integer>() ); totalDurationLinkedBlockingQueueBlocking = totalDurationLinkedBlockingQueueBlocking + blockingQueuePerformanceTest( queueItemCount, new LinkedBlockingQueue<Integer>() ); totalDurationArrayBlockingQueueNonBlocking = totalDurationArrayBlockingQueueNonBlocking + nonBlockingQueuePerformanceTest( queueItemCount, new ArrayBlockingQueue<Integer>( queueItemCount ) ); totalDurationArrayBlockingQueueBlocking = totalDurationArrayBlockingQueueBlocking + blockingQueuePerformanceTest( queueItemCount, new ArrayBlockingQueue<Integer>( queueItemCount ) ); totalDurationLinkedTransferQueueAddPollNonBlocking = totalDurationLinkedTransferQueueAddPollNonBlocking + nonBlockingQueuePerformanceTest( queueItemCount, new LinkedTransferQueue<Integer>() ); totalDurationLinkedTransferQueuePutTakeBlocking = totalDurationLinkedTransferQueuePutTakeBlocking + blockingQueuePerformanceTest( queueItemCount, new LinkedTransferQueue<Integer>() ); totalDurationSynchronousQueueBlocking = totalDurationSynchronousQueueBlocking + blockingQueuePerformanceTest( queueItemCount, new SynchronousQueue<Integer>() ); } long concurrentLinkedQueueNonBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationConcurrentLinkedQueueNonBlocking; long linkedBlockingQueueNonBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationLinkedBlockingQueueNonBlocking; long linkedBlockingQueueBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationLinkedBlockingQueueBlocking; long arrayBlockingQueueNonBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationArrayBlockingQueueNonBlocking; long arrayBlockingQueueBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationArrayBlockingQueueBlocking; long linkedTransferQueueNonBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationLinkedTransferQueueAddPollNonBlocking; long linkedTransferQueueBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationLinkedTransferQueuePutTakeBlocking; long synchronousQueueBlockingItemsPerMs = (queueItemCount * experimentCount) / totalDurationSynchronousQueueBlocking; System.out.println( "ConcurrentLinkedQueue(non-blocking) = \t" + concurrentLinkedQueueNonBlockingItemsPerMs + " item/ms" ); System.out.println( "LinkedBlockingQueue(non-blocking) = \t" + linkedBlockingQueueNonBlockingItemsPerMs + " item/ms" ); System.out .println( "LinkedBlockingQueue(blocking) = \t\t" + linkedBlockingQueueBlockingItemsPerMs + " item/ms" ); System.out.println( "ArrayBlockingQueue(non-blocking) = \t\t" + arrayBlockingQueueNonBlockingItemsPerMs + " item/ms" ); System.out .println( "ArrayBlockingQueue(blocking) = \t\t\t" + arrayBlockingQueueBlockingItemsPerMs + " item/ms" ); System.out.println( "LinkedTransferQueue(non-blocking) = \t" + linkedTransferQueueNonBlockingItemsPerMs + " item/ms" ); System.out .println( "LinkedTransferQueue(blocking) = \t\t" + linkedTransferQueueBlockingItemsPerMs + " item/ms" ); System.out.println( "SynchronousQueue(blocking) = \t\t\t" + synchronousQueueBlockingItemsPerMs + " item/ms" ); } public long nonBlockingQueuePerformanceTest( final int queueItemCount, final Queue<Integer> queue ) throws InterruptedException { Thread writeThread = new Thread() { @Override public void run() { for ( int i = 0; i < queueItemCount; i++ ) { queue.add( i ); } queue.add( TERMINATE ); } }; Thread readThread = new Thread() { @Override public void run() { Integer val = 0; while ( TERMINATE.equals( val ) == false ) { val = queue.poll(); } } }; long startTimeAsMilli = timeSource.nowAsMilli(); readThread.start(); writeThread.start(); writeThread.join(); readThread.join(); assertThat( queue.poll(), is( nullValue() ) ); assertThat( queue.size(), is( 0 ) ); return timeSource.nowAsMilli() - startTimeAsMilli; } public long blockingQueuePerformanceTest( final int queueItemCount, final BlockingQueue<Integer> queue ) throws InterruptedException { Thread writeThread = new Thread() { @Override public void run() { try { for ( int i = 0; i < queueItemCount; i++ ) { queue.put( i ); } queue.put( TERMINATE ); } catch ( InterruptedException e ) { e.printStackTrace(); } } }; Thread readThread = new Thread() { @Override public void run() { try { Integer val = 0; while ( TERMINATE.equals( val ) == false ) { val = queue.take(); } } catch ( InterruptedException e ) { e.printStackTrace(); } } }; long startTimeAsMilli = timeSource.nowAsMilli(); readThread.start(); writeThread.start(); writeThread.join(); readThread.join(); assertThat( queue.poll(), is( nullValue() ) ); assertThat( queue.size(), is( 0 ) ); return timeSource.nowAsMilli() - startTimeAsMilli; } }