Package com.lmax.disruptor

Source Code of com.lmax.disruptor.Sequencer3P1CPerfTest

/*
* Copyright 2011 LMAX Ltd., modified by Jamie Allen to use Scala port.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lmax.disruptor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.junit.Test;

import com.jamieallen.sdisruptor.BatchConsumer;
import com.jamieallen.sdisruptor.ClaimStrategy;
import com.jamieallen.sdisruptor.ConsumerBarrier;
import com.jamieallen.sdisruptor.RingBuffer;
import com.jamieallen.sdisruptor.WaitStrategy;
import com.lmax.disruptor.support.ValueAdditionHandler;
import com.lmax.disruptor.support.ValueAdditionQueueConsumer;
import com.lmax.disruptor.support.ValueEntry;
import com.lmax.disruptor.support.ValueProducer;
import com.lmax.disruptor.support.ValueQueueProducer;

/**
* <pre>
*
* Sequence a series of events from multiple producers going to one consumer.
*
* +----+
* | P0 |------+
* +----+      |
*             v
* +----+    +----+
* | P1 |--->| C1 |
* +----+    +----+
*             ^
* +----+      |
* | P2 |------+
* +----+
*
*
* Queue Based:
* ============
*
* +----+  put
* | P0 |------+
* +----+      |
*             v   take
* +----+    +====+    +----+
* | P1 |--->| Q0 |<---| C0 |
* +----+    +====+    +----+
*             ^
* +----+      |
* | P2 |------+
* +----+
*
* P0 - Producer 0
* P1 - Producer 1
* P2 - Producer 2
* Q0 - Queue 0
* C0 - Consumer 0
*
*
* Disruptor:
* ==========
*             track to prevent wrap
*             +--------------------+
*             |                    |
*             |                    v
* +----+    +====+    +====+    +----+
* | P0 |--->| RB |<---| CB |    | C0 |
* +----+    +====+    +====+    +----+
*             ^   get    ^         |
* +----+      |          |         |
* | P1 |------+          +---------+
* +----+      |            waitFor
*             |
* +----+      |
* | P2 |------+
* +----+
*
* P0 - Producer 0
* P1 - Producer 1
* P2 - Producer 2
* RB - RingBuffer
* CB - ConsumerBarrier
* C0 - Consumer 0
*
* </pre>
*/
public final class Sequencer3P1CPerfTest extends AbstractPerfTestQueueVsDisruptor
{
    private static final int NUM_PRODUCERS = 3;
    private static final int SIZE = 1024 * 32;
    private static final long ITERATIONS = 1000L * 1000L * 100L;
    private final ExecutorService EXECUTOR = Executors.newFixedThreadPool(NUM_PRODUCERS + 1);
    private final CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM_PRODUCERS + 1);

    ///////////////////////////////////////////////////////////////////////////////////////////////

    private final BlockingQueue<Long> blockingQueue = new ArrayBlockingQueue<Long>(SIZE);
    private final ValueAdditionQueueConsumer queueConsumer = new ValueAdditionQueueConsumer(blockingQueue);
    private final ValueQueueProducer[] valueQueueProducers = new ValueQueueProducer[NUM_PRODUCERS];
    {
        valueQueueProducers[0] = new ValueQueueProducer(cyclicBarrier, blockingQueue, ITERATIONS);
        valueQueueProducers[1] = new ValueQueueProducer(cyclicBarrier, blockingQueue, ITERATIONS);
        valueQueueProducers[2] = new ValueQueueProducer(cyclicBarrier, blockingQueue, ITERATIONS);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    private final RingBuffer<ValueEntry> ringBuffer =
        new RingBuffer<ValueEntry>(ValueEntry.ENTRY_FACTORY, SIZE,
                                   ClaimStrategy.Option.MULTI_THREADED,
                                   WaitStrategy.Option.YIELDING);

    private final ConsumerBarrier<ValueEntry> consumerBarrier = ringBuffer.createConsumerBarrier();
    private final ValueAdditionHandler handler = new ValueAdditionHandler();
    private final BatchConsumer<ValueEntry> batchConsumer = new BatchConsumer<ValueEntry>(consumerBarrier, handler);
    private final ValueProducer[] valueProducers = new ValueProducer[NUM_PRODUCERS];
    {
        valueProducers[0] = new ValueProducer(cyclicBarrier, ringBuffer, ITERATIONS);
        valueProducers[1] = new ValueProducer(cyclicBarrier, ringBuffer, ITERATIONS);
        valueProducers[2] = new ValueProducer(cyclicBarrier, ringBuffer, ITERATIONS);

        ringBuffer.setTrackedConsumers(batchConsumer);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////

    @Test
    @Override
    public void shouldCompareDisruptorVsQueues()
        throws Exception
    {
        testImplementations();
    }

    @Override
    protected long runQueuePass(final int passNumber) throws Exception
    {
        Future[] futures = new Future[NUM_PRODUCERS];
        for (int i = 0; i < NUM_PRODUCERS; i++)
        {
            futures[i] = EXECUTOR.submit(valueQueueProducers[i]);
        }
        Future consumerFuture = EXECUTOR.submit(queueConsumer);

        long start = System.currentTimeMillis();
        cyclicBarrier.await();

        for (int i = 0; i < NUM_PRODUCERS; i++)
        {
            futures[i].get();
        }

        final long expectedSequence = (ITERATIONS * NUM_PRODUCERS) - 1L;
        while (expectedSequence > queueConsumer.getSequence())
        {
            // busy spin
        }

        long opsPerSecond = (NUM_PRODUCERS * ITERATIONS * 1000L) / (System.currentTimeMillis() - start);
        batchConsumer.halt();
        consumerFuture.cancel(true);

        return opsPerSecond;
    }

    @Override
    protected long runDisruptorPass(final int passNumber) throws Exception
    {
        Future[] futures = new Future[NUM_PRODUCERS];
        for (int i = 0; i < NUM_PRODUCERS; i++)
        {
            futures[i] = EXECUTOR.submit(valueProducers[i]);
        }
        EXECUTOR.submit(batchConsumer);

        long start = System.currentTimeMillis();
        cyclicBarrier.await();

        for (int i = 0; i < NUM_PRODUCERS; i++)
        {
            futures[i].get();
        }

        final long expectedSequence = (ITERATIONS * NUM_PRODUCERS * (passNumber + 1L)) - 1L;
        while (expectedSequence > batchConsumer.getSequence())
        {
            // busy spin
        }

        long opsPerSecond = (NUM_PRODUCERS * ITERATIONS * 1000L) / (System.currentTimeMillis() - start);
        batchConsumer.halt();

        return opsPerSecond;
    }
}
TOP

Related Classes of com.lmax.disruptor.Sequencer3P1CPerfTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.