@Override protected long runDisruptorPass() throws Exception { CountDownLatch latch = new CountDownLatch(1); fizzBuzzHandler.reset(latch, batchProcessorFizzBuzz.getSequence().get() + ITERATIONS); executor.submit(batchProcessorFizz); executor.submit(batchProcessorBuzz); executor.submit(batchProcessorFizzBuzz); long start = System.currentTimeMillis(); for (long i = 0; i < ITERATIONS; i++) { long sequence = ringBuffer.next(); ringBuffer.get(sequence).setValue(i); ringBuffer.publish(sequence); } latch.await(); long opsPerSecond = (ITERATIONS * 1000L) / (System.currentTimeMillis() - start); batchProcessorFizz.halt(); batchProcessorBuzz.halt(); batchProcessorFizzBuzz.halt(); Assert.assertEquals(expectedResult, fizzBuzzHandler.getFizzBuzzCounter()); return opsPerSecond; }
/** * * * <pre> * Produce an event replicated to two event processors and fold back to a single third event processor. * * +-----+ * +----->| EP1 |------+ * | +-----+ | * | v * +----+ +-----+ * | P1 | | EP3 | * +----+ +-----+ * | ^ * | +-----+ | * +----->| EP2 |------+ * +-----+ * * * Queue Based: * ============ * take put * put +====+ +-----+ +====+ take * +----->| Q1 |<---| EP1 |--->| Q3 |<------+ * | +====+ +-----+ +====+ | * | | * +----+ +====+ +-----+ +====+ +-----+ * | P1 |--->| Q2 |<---| EP2 |--->| Q4 |<---| EP3 | * +----+ +====+ +-----+ +====+ +-----+ * * P1 - Publisher 1 * Q1 - Queue 1 * Q2 - Queue 2 * Q3 - Queue 3 * Q4 - Queue 4 * EP1 - EventProcessor 1 * EP2 - EventProcessor 2 * EP3 - EventProcessor 3 * * * Disruptor: * ========== * track to prevent wrap * +-------------------------------+ * | | * | v * +----+ +====+ +=====+ +-----+ * | P1 |--->| RB |<--------------| SB2 |<---| EP3 | * +----+ +====+ +=====+ +-----+ * claim ^ get | waitFor * | | * +=====+ +-----+ | * | SB1 |<---| EP1 |<-----+ * +=====+ +-----+ | * ^ | * | +-----+ | * +-------| EP2 |<-----+ * waitFor +-----+ * * P1 - Publisher 1 * RB - RingBuffer * SB1 - SequenceBarrier 1 * EP1 - EventProcessor 1 * EP2 - EventProcessor 2 * SB2 - SequenceBarrier 2 * EP3 - EventProcessor 3 * * </pre> */ public final class OnePublisherToThreeProcessorDiamondThroughputTest extends AbstractPerfTestQueueVsDisruptor { private static final int NUM_EVENT_PROCESSORS = 3; private static final int BUFFER_SIZE = 1024 * 8; private static final long ITERATIONS = 1000L * 1000L * 100L; private final ExecutorService executor = Executors.newFixedThreadPool(NUM_EVENT_PROCESSORS); private final long expectedResult; { long temp = 0L; for (long i = 0; i < ITERATIONS; i++) { boolean fizz = 0 == (i % 3L); boolean buzz = 0 == (i % 5L); if (fizz && buzz) { ++temp; } } expectedResult = temp; } /////////////////////////////////////////////////////////////////////////////////////////////// private final BlockingQueue<Long> fizzInputQueue = new LinkedBlockingQueue<Long>(BUFFER_SIZE); private final BlockingQueue<Long> buzzInputQueue = new LinkedBlockingQueue<Long>(BUFFER_SIZE); private final BlockingQueue<Boolean> fizzOutputQueue = new LinkedBlockingQueue<Boolean>(BUFFER_SIZE); private final BlockingQueue<Boolean> buzzOutputQueue = new LinkedBlockingQueue<Boolean>(BUFFER_SIZE); private final FizzBuzzQueueProcessor fizzQueueProcessor = new FizzBuzzQueueProcessor( FizzBuzzStep.FIZZ, fizzInputQueue, buzzInputQueue, fizzOutputQueue, buzzOutputQueue, ITERATIONS - 1); private final FizzBuzzQueueProcessor buzzQueueProcessor = new FizzBuzzQueueProcessor( FizzBuzzStep.BUZZ, fizzInputQueue, buzzInputQueue, fizzOutputQueue, buzzOutputQueue, ITERATIONS - 1); private final FizzBuzzQueueProcessor fizzBuzzQueueProcessor = new FizzBuzzQueueProcessor( FizzBuzzStep.FIZZ_BUZZ, fizzInputQueue, buzzInputQueue, fizzOutputQueue, buzzOutputQueue, ITERATIONS - 1); /////////////////////////////////////////////////////////////////////////////////////////////// private final RingBuffer<FizzBuzzEvent> ringBuffer = createSingleProducer(FizzBuzzEvent.EVENT_FACTORY, BUFFER_SIZE, new YieldingWaitStrategy()); private final SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); private final FizzBuzzEventHandler fizzHandler = new FizzBuzzEventHandler(FizzBuzzStep.FIZZ); private final BatchEventProcessor<FizzBuzzEvent> batchProcessorFizz = new BatchEventProcessor<FizzBuzzEvent>(ringBuffer, sequenceBarrier, fizzHandler); private final FizzBuzzEventHandler buzzHandler = new FizzBuzzEventHandler(FizzBuzzStep.BUZZ); private final BatchEventProcessor<FizzBuzzEvent> batchProcessorBuzz = new BatchEventProcessor<FizzBuzzEvent>(ringBuffer, sequenceBarrier, buzzHandler); private final SequenceBarrier sequenceBarrierFizzBuzz = ringBuffer.newBarrier(batchProcessorFizz.getSequence(), batchProcessorBuzz.getSequence()); private final FizzBuzzEventHandler fizzBuzzHandler = new FizzBuzzEventHandler(FizzBuzzStep.FIZZ_BUZZ); private final BatchEventProcessor<FizzBuzzEvent> batchProcessorFizzBuzz = new BatchEventProcessor<FizzBuzzEvent>(ringBuffer, sequenceBarrierFizzBuzz, fizzBuzzHandler); { ringBuffer.addGatingSequences(batchProcessorFizzBuzz.getSequence()); } /////////////////////////////////////////////////////////////////////////////////////////////// @Override protected int getRequiredProcessorCount() { return 4; } @Test @Override public void shouldCompareDisruptorVsQueues() throws Exception { testImplementations(); } @Override protected long runQueuePass() throws Exception { final CountDownLatch latch = new CountDownLatch(1); fizzBuzzQueueProcessor.reset(latch); Future<?>[] futures = new Future[NUM_EVENT_PROCESSORS]; futures[0] = executor.submit(fizzQueueProcessor); futures[1] = executor.submit(buzzQueueProcessor); futures[2] = executor.submit(fizzBuzzQueueProcessor); long start = System.currentTimeMillis(); for (long i = 0; i < ITERATIONS; i++) { Long value = Long.valueOf(i); fizzInputQueue.put(value); buzzInputQueue.put(value); } latch.await(); long opsPerSecond = (ITERATIONS * 1000L) / (System.currentTimeMillis() - start); fizzQueueProcessor.halt(); buzzQueueProcessor.halt(); fizzBuzzQueueProcessor.halt(); for (Future<?> future : futures) { future.cancel(true); } Assert.assertEquals(expectedResult, fizzBuzzQueueProcessor.getFizzBuzzCounter()); return opsPerSecond; } @Override protected long runDisruptorPass() throws Exception { CountDownLatch latch = new CountDownLatch(1); fizzBuzzHandler.reset(latch, batchProcessorFizzBuzz.getSequence().get() + ITERATIONS); executor.submit(batchProcessorFizz); executor.submit(batchProcessorBuzz); executor.submit(batchProcessorFizzBuzz); long start = System.currentTimeMillis(); for (long i = 0; i < ITERATIONS; i++) { long sequence = ringBuffer.next(); ringBuffer.get(sequence).setValue(i); ringBuffer.publish(sequence); } latch.await(); long opsPerSecond = (ITERATIONS * 1000L) / (System.currentTimeMillis() - start); batchProcessorFizz.halt(); batchProcessorBuzz.halt(); batchProcessorFizzBuzz.halt(); Assert.assertEquals(expectedResult, fizzBuzzHandler.getFizzBuzzCounter()); return opsPerSecond; } }
{ ringBuffer.addGatingSequences(batchProcessorFizzBuzz.getSequence()); }
public TestShow() { ringBuffer.addGatingSequences(batchEventProcessor.getSequence()); }