Package com.lmax.disruptor

Source Code of com.lmax.disruptor.DiamondPath1P3CPerfTest

/*
* 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.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.junit.Assert;
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.FizzBuzzEntry;
import com.lmax.disruptor.support.FizzBuzzHandler;
import com.lmax.disruptor.support.FizzBuzzQueueConsumer;
import com.lmax.disruptor.support.FizzBuzzStep;

/**
* <pre>
* Produce an event replicated to two consumers and fold back to a single third consumer.
*
*           +----+
*    +----->| C0 |-----+
*    |      +----+     |
*    |                 v
* +----+             +----+
* | P0 |             | C2 |
* +----+             +----+
*    |                 ^
*    |      +----+     |
*    +----->| C1 |-----+
*           +----+
*
*
* Queue Based:
* ============
*                 take       put
*     put   +====+    +----+    +====+  take
*    +----->| Q0 |<---| C0 |--->| Q2 |<-----+
*    |      +====+    +----+    +====+      |
*    |                                      |
* +----+    +====+    +----+    +====+    +----+
* | P0 |--->| Q1 |<---| C1 |--->| Q3 |<---| C2 |
* +----+    +====+    +----+    +====+    +----+
*
* P0 - Producer 0
* Q0 - Queue 0
* Q1 - Queue 1
* Q2 - Queue 2
* Q3 - Queue 3
* C0 - Consumer 0
* C1 - Consumer 1
* C2 - Consumer 2
*
*
* Disruptor:
* ==========
*               track to prevent wrap
*              +---------------------+
*              |                     |
*              |                     v
* +----+    +====+     +=====+    +----+
* | P0 |--->| RB |<----| CB1 |<---| C2 |
* +----+    +====+     +=====+    +----+
*      claim   ^  get               |   waitFor
*              |                    |
*           +=====+    +----+       |
*           | CB0 |<---| C0 |<------+
*           +=====+    +----+       |
*              ^                    |
*              |       +----+       |
*              +-------| C1 |<------+
*            waitFor   +----+
*
* P0  - Producer 0
* RB  - RingBuffer
* CB0 - ConsumerBarrier 0
* C0  - Consumer 0
* C1  - Consumer 1
* CB1 - ConsumerBarrier 1
* C2  - Consumer 2
*
* </pre>
*/
public final class DiamondPath1P3CPerfTest extends AbstractPerfTestQueueVsDisruptor
{
    private static final int NUM_CONSUMERS = 3;
    private static final int SIZE = 1024 * 32;
    private static final long ITERATIONS = 1000 * 1000 * 500;
    private final ExecutorService EXECUTOR = Executors.newFixedThreadPool(NUM_CONSUMERS);

    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 ArrayBlockingQueue<Long>(SIZE);
    private final BlockingQueue<Long> buzzInputQueue = new ArrayBlockingQueue<Long>(SIZE);
    private final BlockingQueue<Boolean> fizzOutputQueue = new ArrayBlockingQueue<Boolean>(SIZE);
    private final BlockingQueue<Boolean> buzzOutputQueue = new ArrayBlockingQueue<Boolean>(SIZE);

    private final FizzBuzzQueueConsumer fizzQueueConsumer =
        new FizzBuzzQueueConsumer(FizzBuzzStep.FIZZ, fizzInputQueue, buzzInputQueue, fizzOutputQueue, buzzOutputQueue);

    private final FizzBuzzQueueConsumer buzzQueueConsumer =
        new FizzBuzzQueueConsumer(FizzBuzzStep.BUZZ, fizzInputQueue, buzzInputQueue, fizzOutputQueue, buzzOutputQueue);

    private final FizzBuzzQueueConsumer fizzBuzzQueueConsumer =
        new FizzBuzzQueueConsumer(FizzBuzzStep.FIZZ_BUZZ, fizzInputQueue, buzzInputQueue, fizzOutputQueue, buzzOutputQueue);

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

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

    private final ConsumerBarrier<FizzBuzzEntry> consumerBarrier = ringBuffer.createConsumerBarrier();

    private final FizzBuzzHandler fizzHandler = new FizzBuzzHandler(FizzBuzzStep.FIZZ);
    private final BatchConsumer<FizzBuzzEntry> batchConsumerFizz =
        new BatchConsumer<FizzBuzzEntry>(consumerBarrier, fizzHandler);

    private final FizzBuzzHandler buzzHandler = new FizzBuzzHandler(FizzBuzzStep.BUZZ);
    private final BatchConsumer<FizzBuzzEntry> batchConsumerBuzz =
        new BatchConsumer<FizzBuzzEntry>(consumerBarrier, buzzHandler);

    private final ConsumerBarrier<FizzBuzzEntry> consumerBarrierFizzBuzz =
        ringBuffer.createConsumerBarrier(batchConsumerFizz, batchConsumerBuzz);

    private final FizzBuzzHandler fizzBuzzHandler = new FizzBuzzHandler(FizzBuzzStep.FIZZ_BUZZ);
    private final BatchConsumer<FizzBuzzEntry> batchConsumerFizzBuzz =
            new BatchConsumer<FizzBuzzEntry>(consumerBarrierFizzBuzz, fizzBuzzHandler);
    {
        ringBuffer.setTrackedConsumers(batchConsumerFizzBuzz);
    }

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

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

    @Override
    protected long runDisruptorPass(int PassNumber) throws Exception
    {
        fizzBuzzHandler.reset();

        EXECUTOR.submit(batchConsumerFizz);
        EXECUTOR.submit(batchConsumerBuzz);
        EXECUTOR.submit(batchConsumerFizzBuzz);

        long start = System.currentTimeMillis();

        for (long i = 0; i < ITERATIONS; i++)
        {
            FizzBuzzEntry entry = ringBuffer.nextEntry();
            entry.setValue(i);
            ringBuffer.commit(entry);
        }

        final long expectedSequence = ringBuffer.getCursor();
        while (batchConsumerFizzBuzz.getSequence() < expectedSequence)
        {
            // busy spin
        }

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

        batchConsumerFizz.halt();
        batchConsumerBuzz.halt();
        batchConsumerFizzBuzz.halt();

        Assert.assertEquals(expectedResult, fizzBuzzHandler.getFizzBuzzCounter());

        return opsPerSecond;
    }

    @Override
    protected long runQueuePass(int passNumber) throws Exception
    {
        fizzBuzzQueueConsumer.reset();

        Future[] futures = new Future[NUM_CONSUMERS];
        futures[0] = EXECUTOR.submit(fizzQueueConsumer);
        futures[1] = EXECUTOR.submit(buzzQueueConsumer);
        futures[2] = EXECUTOR.submit(fizzBuzzQueueConsumer);

        long start = System.currentTimeMillis();

        for (long i = 0; i < ITERATIONS; i++)
        {
            Long value = Long.valueOf(i);
            fizzInputQueue.put(value);
            buzzInputQueue.put(value);
        }

        final long expectedSequence = ITERATIONS - 1;
        while (fizzBuzzQueueConsumer.getSequence() < expectedSequence)
        {
            // busy spin
        }

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

        fizzQueueConsumer.halt();
        buzzQueueConsumer.halt();
        fizzBuzzQueueConsumer.halt();

        for (Future future : futures)
        {
            future.cancel(true);
        }

        Assert.assertEquals(expectedResult, fizzBuzzQueueConsumer.getFizzBuzzCounter());

        return opsPerSecond;
    }
}
TOP

Related Classes of com.lmax.disruptor.DiamondPath1P3CPerfTest

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.