GithubHelp home page GithubHelp logo

lmax-exchange / disruptor Goto Github PK

View Code? Open in Web Editor NEW
17.0K 1.2K 3.9K 9.62 MB

High Performance Inter-Thread Messaging Library

Home Page: http://lmax-exchange.github.io/disruptor/

License: Apache License 2.0

Java 99.97% Shell 0.03%
disruptor java concurrency

disruptor's Introduction

disruptor's People

Contributors

a248 avatar ajsutton avatar boreplusplus avatar carterkozak avatar codeaholics avatar danielnorberg avatar davef77 avatar grumpyjames avatar isolgpus avatar jasonk000 avatar kscaldef avatar mendelmonteiro avatar mikeb01 avatar mjpt777 avatar mzheravin avatar nicholassm avatar nitsanw avatar ocoanet avatar palmr avatar prolic avatar ptravers avatar ramsrib avatar rookiexu avatar sambarker avatar sea36 avatar steafanmrzhou avatar sullis avatar swarren12 avatar thebeanogamer avatar willemsst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

disruptor's Issues

Problem with handleEventWith.then [moved]

This is Issue 26 moved from a Google Code project.
Added by 2012-07-21T18:14:09.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Invalid).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>
1. disruptor.handleEventsWith(new Handler1(),new Handler2()).then(new LogHandler());
<b>2.</b>
<b>3.</b>

<b>What is the expected output? What do you see instead?</b>
the Handler1() and Handler2() run first then follow by LogHandler()

but 

Handler1() not running, and LogHandler() not running...

<b>What version of the product are you using? On what operating system?</b>
windows 7

<b>Please provide any additional information below.</b>

Wrong contract of translateTo() method in EventTranslator interface [moved]

This is Issue 22 moved from a Google Code project.
Added by 2012-05-19T13:16:23.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

I think there is a big bug in EventTranslator interface. EventTranslator define a T translateTo(T event, long sequence) method. So one hopes that translateTo() method returns something.
After looking at EventPublisher object source, one can read :

{{{
private void translateAndPublish(final EventTranslator<E> translator, final long sequence)
{
   try
   {
       translator.translateTo(ringBuffer.get(sequence), sequence);
   }
   finally
   {
       ringBuffer.publish(sequence);
   }
}
}}}

*So method translateTo() is called but never wait for a return.*

You can even return null in the translateTo() method, no problem ! :

_(EventWrapper is a simple POJO wrapping a T event)_
{{{
public EventWrapper translateTo(final EventWrapper event, final long sequence) {
    event.setEvent(wrappedEvent);
    return null;
}
}}}

Message to disruptor developers You may define the translateTo() method in the EventTranslator interface as
{{{
<T> void translateTo(T event, long sequence)
}}}

move to git or hg [moved]

This is Issue 24 moved from a Google Code project.
Added by 2012-07-04T12:37:34.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Task, Priority-Low

Original description

Better have a cloned repo, than checking out specific versions :)

Awesome work btw!

Publish to Maven Central [moved]

This is Issue 2 moved from a Google Code project.
Added by 2011-07-15T02:32:57.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Priority-Medium, Type-Enhancement

Original description

<b>What steps will reproduce the problem?</b>
1. Disruptor project is not available through Maven  Centrall

<b>What is the expected output? What do you see instead?</b>
I would like to import the disruptor library as a maven dependency like so:
<dependency>
    <groupId>uk.co.lmaxtrader</groupId>
    <artifactId>distruptor</artifactId>
    <version>1.2.1</version>
</dependency>

<b>What version of the product are you using? On what operating system?</b>
All versions. All OSes

<b>Please provide any additional information below.</b>
Sonatype provides free maven repository pushes for open source projects:

https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide 
https://oss.sonatype.org/

I use them for my projects with great success and have had no problems.

BatchEventProcessor un-teriminate [moved]

This is Issue 17 moved from a Google Code project.
Added by 2012-03-04T14:08:22.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (WontFix).

Original labels: Type-Defect, Priority-Medium

Original description

AssertionError: Failed to stop thread[BatchEventProcess@...]
d.dsl.stubs.StubExecutor.joinAllThreads
d.dsl.DisruptorTest.tearDown

shouldMakeEntriesAvailableToFirstHandlersImmediately

Test running at Win7 64 with AMD core3, and jdk7 u3
Not often,  the chance in my machine about 10 percent.

javadoc: package.html example anonymous EventFactory interface wrong [moved]

This is Issue 20 moved from a Google Code project.
Added by 2012-04-16T12:59:39.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

In version 2.9 and current SVN trunk, there is an error in the com.lmax.disruptor javadoc; here is the fix:

$ svn diff
Index: code/src/main/com/lmax/disruptor/package.html
===================================================================
--- code/src/main/com/lmax/disruptor/package.html       (revision 538)
+++ code/src/main/com/lmax/disruptor/package.html       (working copy)
@@ -132,7 +132,7 @@

         public final static EventFactory&lt;ValueEvent&gt; EVENT_FACTORY = new EventFactory&lt;ValueEvent&gt;()
         {
-            public ValueEvent create()
+            public ValueEvent newInstance()
             {
                 return new ValueEvent();
             }

very very Slowly.why?

I use workpool, 10 producer,11consumer

consumer code:

public class WorkEventsTwoPubrHandle  implements WorkHandler<ValueEvent>
{
..................
    @Override
    public void onEvent(final ValueEvent event) throws Exception
    {       
        //dosomething
        Thread.Sleep(1000L)
        //dosomething
    }
}

the workpool become very very Slowly.why?

DisruptorTest is failing

Testcase failure

all > com.lmax.disruptor.dsl > DisruptorTest

Here is the error


java.lang.AssertionError: Failed to stop thread: Thread[com.lmax.disruptor.BatchEventProcessor@4cad4d40,5,main]
at org.junit.Assert.fail(Assert.java:91)
at org.junit.Assert.assertTrue(Assert.java:43)
at org.junit.Assert.assertFalse(Assert.java:68)
at com.lmax.disruptor.dsl.stubs.StubExecutor.joinAllThreads(StubExecutor.java:63)
at com.lmax.disruptor.dsl.DisruptorTest.tearDown(DisruptorTest.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:37)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:55)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:42)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:71)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:49)
at sun.reflect.GeneratedMethodAccessor7.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at $Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:103)
at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

at java.lang.Thread.run(Thread.java:662)

several invocations of different RingBuffers from same thread are leading to misbehavior [moved]

This is Issue 10 moved from a Google Code project.
Added by 2011-09-14T15:59:13.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>

1. create several small (capacity=2) RingBuffers using ClaimStrategy.Option.MULTI_THREADED
2. create a RingBuffer, take all sequences, publish first, take another sequence
3. create another RingBuffer, take all sequences, RingBuffer#hasAvailableCapacity yields true


<b>What is the expected output? What do you see instead?</b>

RingBuffer#hasAvailableCapacity should yield false


<b>Please provide any additional information below.</b>

This issue was introduced with revision 362 and is caused by the static ThreadLocal minGatingSequenceThreadLocal in ClaimStrategy.java line 115. Removing the static modifier
(eg ThreadLocal per instance) solves the issue and gives every RingBuffer its own minGatingSequenceThreadLocal as it should be.


I have attached patch including a TestCase and the fix as mentioned above.

Minor javadoc tweak [moved]

This is Issue 25 moved from a Google Code project.
Added by 2012-07-16T14:47:53.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

In Disruptor.java, &quot;handleEventException&quot; should be changed to &quot;handle&quot; in the javadocs:

&quot;Set up event handlers to handleEventException events from the ring buffer.&quot;

&quot;Set up custom event processors to handleEventException events from the ring buffer.&quot;

This was changed by commit r468, but I think the IDE was too eager and shouldn't have renamed these when renaming ExceptionHandler#handle() to ExceptionHandler#handleEventException().

push disruptor 2.10.3 to a public maven repo

It looks like version 2.10.3 hasn't been published anywhere. I'd like to depend on it in an open source library and not being able to just plop it into a pom file would make distribution much more difficult. Mind doing that?

BatchEventProcessor does not catch types that derive from Error [moved]

This is Issue 13 moved from a Google Code project.
Added by 2011-11-01T20:53:34.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>
1. Throw an AssertionError when handling an event

<b>What is the expected output? What do you see instead?</b>
I'd like to see the exception handler be triggered. Or alternatively be allowed to provide a different hook for handling derived types of Error.


<b>What version of the product are you using? On what operating system?</b>
2.6, different flavors of Linux


<b>Please provide any additional information below.</b>
I am using the Disruptor in Scala. The reproduction step listed above is the easiest way to see this. In production we elide out assertions, but if other derived types of Error are thrown, we don't get notified via the exception handler.

TimeoutBlockingWaitStrategy caurse high cpu occured.

Disruptor provides sereral kinds of WaitStrtegy. As request-reply is common used while sometimes we should wait the result to return which might cause high CPU.Here comes the stacktrace :
ForkJoinPool-20-worker-29" daemon prio=10 tid=0x08c68c00 nid=0x63c9 waiting on condition [0xd07f0000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0xd8802770> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
at com.lmax.disruptor.TimeoutBlockingWaitStrategy.waitFor(TimeoutBlockingWaitStrategy.java:37)
at com.lmax.disruptor.ProcessingSequenceBarrier.waitFor(ProcessingSequenceBarrier.java:55)
at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:123)
at jsr166y.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1361)
at jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:260)
at jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:988)
at jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1629)
at jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

Locked ownable synchronizers:
- None

such could be viewd and generated through jstack pid > XX.txt and trace the
orignal for anaysis which line 37 showed where the problem was.

Variable gatingSequences value๏ผŒ How do change it? This problem has troubled me

hi๏ผŒ
I read Disruptor๏ผˆjava 3.1.1๏ผ‰ source code,Problems are as follows๏ผš
๏ผˆclass file MultiProducerSequencer.java๏ผ‰

/**
 * @see Sequencer#next(int)
 */
@Override
public long next(int n)
{
    if (n < 1)
    {
        throw new IllegalArgumentException("n must be > 0");
    }
    long current;
    long next;
    do
    {
        current = cursor.get();
        next = current + n;

        long wrapPoint = next - bufferSize;
        long cachedGatingSequence = gatingSequenceCache.get();

        if (wrapPoint > cachedGatingSequence || cachedGatingSequence > current)
        {
            long gatingSequence = Util.getMinimumSequence(gatingSequences, current);
            if(next==32)
            {
                System.out.println("wrapPoint="+wrapPoint+
                                   ",,gatingSequence="+gatingSequence+
                                   ",,current="+current+
                                   ",,wrapPoint=" + wrapPoint+
                                   ",,cachedGatingSequence=" + cachedGatingSequence);
            }
            if (wrapPoint > gatingSequence)
            {
                LockSupport.parkNanos(1); // TODO, should we spin based on the wait strategy?
                continue;
            }

            gatingSequenceCache.set(gatingSequence);
        }
        else if (cursor.compareAndSet(current, next))
        {
            break;
        }
    }
    while (true);

    return next;
}

Variable gatingSequences value๏ผŒ How do change it? This problem has troubled me๏ผŒ

MultiProducerSequencer.getHighestPublishedSequence coude be very slow

when I run TwoPublisherToTwoProcessorWorkProcessorThroughputTest,only got a speed at about 6000/s. the DependentSeq is 10,000 greater than WorkingSeq,this meaning each event will loop 10,000+.

then i just modify this method as showing below,the test result much faster.
for (long sequence = lowerBound; sequence <= availableSequence; sequence++)
{
if (isAvailable(sequence))
{
return sequence;
}
}

Run 10, Disruptor=8,928,571 ops/sec
Run 11, Disruptor=8,771,929 ops/sec
Run 12, Disruptor=8,695,652 ops/sec
Run 13, Disruptor=7,299,270 ops/sec
Run 14, Disruptor=8,130,081 ops/sec
Run 15, Disruptor=7,812,500 ops/sec
Run 16, Disruptor=8,196,721 ops/sec
Run 17, Disruptor=8,196,721 ops/sec
Run 18, Disruptor=7,936,507 ops/sec
Run 19, Disruptor=8,196,721 ops/sec

How could one contribute? [moved]

This is Issue 23 moved from a Google Code project.
Added by 2012-05-31T06:59:30.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Done).

Original labels: Type-Defect, Priority-Medium

Original description

There are a couple of improvements we've made, are you open to contributions?
Regards,
SK

Support for Multiple Consumers Enabling the Worker Pattern

From a black box perspective, the consumers in disruptor (event handlers) works much like a JMS topic non-durable consumer: Given the messages A, B and C sent to the queue, each consumer connected to the queue will receive the messages A, B and C. The main difference from a topic is that the messages are not copied and each consumer can make changes to the message, making the consumers work like a responsibility chain.

Nevertheless, it would be nice to have the JMS Queue behavior support in disruptor: Given the messages A, B and C, each message will be consumed by only one consumer. With this feature the worker pattern can be supported and a broaden type of applications can benefit from the disruptor pattern, simplified programming model and (maybe) performance advantages that disruptor has brought

Observation: I used JMS only to illustrate the behavior differences between topics and queues. Its not my intention to have disruptor support JMS

waitForFreeSlotAt() uses LockSupport.parkNanos(1L) can take up to 15ms on Windows [moved]

This is Issue 16 moved from a Google Code project.
Added by 2012-01-10T10:17:07.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Defect, Priority-Medium

Original description

I wrote a simple performance test using the Disruptor to test mostly-empty and mostly-full scenarios in the ring buffer.

The SingleThreadedClaimStrategy() provides waitForFreeSlotAt() to block until a place in the ring buffer is available. Within waitForFreeSlotAt() the thread is parked repeatedly using LockSupport.parkNanos(1L) until a place on the ring buffer is available.

LockSupport.parkNanos() uses the JVM to unsafe.park() the LWP in the OS.

I tested the delay of LockSupport.parkNanos(1L) in 3 environments:

a) Windows 7/32bit with i7 M620 @2.67 GHz with Java 1.6.0_23
b) Solaris 10 5/08 s10s_u5wos_10 SPARC VII with Java 1.6.0_22
c) Linux Redhat 2.6.18-194.el5 with AMD Opteron(tm) Processor 6164 with Java 1.6.0_29

with the following findings:
a) avg park() delay times are around 15 millisenconds
b) avg park() delay times are around 6 microsenconds
c) avg park() delay times are around 8 microsenconds

I am confused by the much longer delay of unsafe.park() in my Windows machine, compared to Linux and Solaris.

Testing the Disruptor with a BusySpinWaitStrategy() for 100000 objects on Windows I find:
a) waitForFreeSlotAt() using LockSupport.parkNanos(1L) (unmodified)
       min   0.384 us
      mean  17.272 us
      max 8488.585 us
   std dev 108.792 us

b) waitForFreeSlotAt() using Thread.yield() instead of LockSupport.parkNanos(1L)
       min   0.000 us
      mean   0.420 us
      max 4692.955 us
   std dev  21.881 us

b) waitForFreeSlotAt() using BusyLoop (just an empty while loop)
       min   0.000 us
      mean   0.259 us
       max 236.745 us
   std dev   0.921 us


If you can reproduce the delays of LockSupport.parkNanos(1L) in your environment, I suggest to change waitForFreeSlotAt() to use Thread.yield() instead of LockSupport.parkNanos(1L)


Fantastic work. Thank you.

Can't build from source.

When I run 'gradle build' in master branch using gradle 1.3,
I got error message like this:

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':signArchives'.

    Cannot perform signing task ':signArchives' because it has no configured signatory

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

WorkerPool failed [moved]

This is Issue 19 moved from a Google Code project.
Added by 2012-03-07T14:14:42.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Invalid).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>
1. run OnePublisherToThreeWorkerPoolThroughputTest, repeat with be more patient 
2. in console, the chance of fail less than in IDE, f.e. eclipse
3. the test will hang

<b>What is the expected output? What do you see instead?</b>
when repeat the fail result once, try again in a debug env:
check out the threads, main should loop at YieldWaitStrategy, 
which dependency is right buffer size+1, so it right fail

<b>What version of the product are you using? On what operating system?</b>
svn version, should be 2.8, Win7 on AMD x3  with JDK7 or 8

<b>Please provide any additional information below.</b>
And seems the executor almost verry not fair, so the dependency difference so big and so fail.
The origin code, cpus is 4 wanted, it modified by my system to 3, and the NUM_WORKERS constant changed accordingly.

Outdated test javadoc and class name

The class javadocs of com.lmax.disruptor.TwoPublisherToTwoProcessorWorkProcessorThroughputTest are identical to com.lmax.disruptor.ThreePublisherToOneProcessorSequencedThroughputTest - the diagrams should be updated to have two publishers and two processors to match the test name. Also the first diagram in them mentions "P1" twice instead of "P2".

Though com.lmax.disruptor.TwoPublisherToTwoProcessorWorkProcessorThroughputTest says "TwoPublisher" in its class name, the number of publishers is set to private static final int NUM_PUBLISHERS = 1; Either the number should be changed, or the class name changed to reflect the number of publishers. I tried changing the constant, but that seems to make the test never finish, so I'll just report the issue here instead of making a pull request, so you can decide what the test should be like. :)

Another way to avoid False Sharing [moved]

This is Issue 18 moved from a Google Code project.
Added by 2012-03-04T19:06:29.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Invalid).

Original labels: Type-Defect, Priority-Medium

Original description

I checked out the False Sharing sample, modify the long value wrapper to a nested long value wrapper, seems more efficient:)
The main point just like this:

public final static class LongValue {
        public long value;
}

public final static class VolatileLong {
        public final LongValue value = new LongValue();
}
Some test results show at least 5x better.
If it ok, the Sequence maybe retire:)

The whole code:
public final class FalseSharing2 implements Runnable {
    public final static int NUM_THREADS = 4; // change
    public final static long ITERATIONS = 500L * 1000L * 1000L;
    private final int arrayIndex;

    private static VolatileLong[] longs = new VolatileLong[NUM_THREADS];
    static {
        for (int i = 0; i < longs.length; i++) {
            longs[i] = new VolatileLong();
        }
    }

    public FalseSharing2(final int arrayIndex) {
        this.arrayIndex = arrayIndex;
    }

    public static void main(final String[] args) throws Exception {
        final long start = System.nanoTime();
        runTest();
        System.out.printf(&quot;duration %,d \n&quot;, (System.nanoTime() - start));
    }

    private static void runTest() throws InterruptedException {
        Thread[] threads = new Thread[NUM_THREADS];

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new FalseSharing2(i));
        }

        for (Thread t : threads) {
            t.start();
        }

        for (Thread t : threads) {
            t.join();
        }
    }

    public void run() {
        long i = ITERATIONS + 1;
        while (0 != --i) {
            longs[arrayIndex].value.value = i;
        }
    }

    public final static class LongValue {
        public long value;
    }

    public final static class VolatileLong {
        public final LongValue value = new LongValue();
        // 1,150,255,587 Nest value
        // 1,015,843,430
        // 955,585,491
        // 11,305,826,270 //longs padding
        // 66,421,136,612 // no padding
        // 5,911,999,787 //long[8] paddings
        // 5,716,804,521
        // 5,748,131,849 long[7] padding
        // 5,854,105,701
        // 5,828,358,423
        // 5,797,533,843
        // 5,713,556,973 long[16] padding
        // 5,901,405,576 //long[6] paddings
        // 14,815,210,202 long[1] paddings
        // 11,429,162,478 //longs padding
        // 50,789,779,317 string padding
        // 50,965,117,605
        // 14,669,913,192 string[1] padding
        // 5,672,750,830 byte[56] padding
        // 5,712,467,516
        // 5,847,267,588
        // 5,654,530,766
        // 12,797,977,884 byte[32] long byte[32]
        // 13,928,776,237 byte[63] long byte[63]
        // 10,741,697,472 long[7] long long[7]
        // 12,004,346,192
        // 5,653,926,506
        // 5,797,767,244
        // 5,655,366,476
        // 5,767,881,114
        // 5,944,711,137
        // 5,611,998,754
        // public long p1, p2, p3, p4, p5, p6; // comment out
        // public long[] paddings = new long[7];
        // public byte[] padding2 = new byte[56];
    }
}

Calls to LifecycleAware.{onStart, onShutdown} are not wrapped in an exception handling block [moved]

This is Issue 14 moved from a Google Code project.
Added by 2011-11-01T21:04:19.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>
1. Throw an exception in onStart 


<b>What is the expected output? What do you see instead?</b>
I'd like to see a hook for handling these exceptions. See the additional information below for how I handle exceptions at any point of the event handler's lifetime consistently.


<b>What version of the product are you using? On what operating system?</b>
2.6, various flavors of Linux.


<b>Please provide any additional information below.</b>
I am using the Disruptor in Scala. I ended up building a mixin trait that is mixed in to implementors of LifecycleAware at declaration time. 

The mixin surrounds calls to onStart/onShutdown methods of the decorated class with a try/catch. Its exception handler defaults to logging the exception but can be overridden.

trait BackgroundThreadExceptionHandler {
    def onException(exception: WrappedException)
  }

I wire the custom exception handler into the disruptor by adapting it to the disruptor's exception handler. The handle(exception, sequence, event) method builds an instance of the WrappedException type above from the parameters and invokes the custom handler. This allows me to achieve consistent error handling for the lifetime of onStart/run/onShutdown.

Compute the expected result by using an arithmetic series instead of looping and adding [moved]

This is Issue 7 moved from a Google Code project.
Added by 2011-08-11T22:38:51.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Priority-Medium, Type-Enhancement

Original description

Not an issue per se. I just noticed it when looking over the tests and it seemed strange.

The expected result for UniCast unit tests is computed by a loop and an accumulator.
An arithmetic series could be used instead. 
Also the code is duplicated. 

Added getArithmeticSeries to Utils and removed duplication.

Perhaps a less general formula like n(n-1)/2 and single parameter method could be used instead for simplicity. 

Typo on the front page [moved]

This is Issue 1 moved from a Google Code project.
Added by 2011-06-22T17:10:45.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Done).

Original labels: Type-Defect, Priority-Medium

Original description

The following text:

2. Build a distribution

    > cd ${MY_PROJECTS_HOME}/disruptor/code
    > ant

Should probably read as follows:

2. Build a distribution

    > cd ${MY_PROJECTS_HOME}/disruptor-read-only/code
    > ant

Pendantry done.

Matt.

passing en empty Array into Disruptor.then() causes elements in the ring buffer to be overwritten before passed to an handler [moved]

This is Issue 12 moved from a Google Code project.
Added by 2011-09-27T07:47:51.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>
1. Instantiate a Disruptor, using the dsl 
2. invoke Disruptor.handleEventsWith(), passing a proper event handler
3. invoke Disruptor.then() passing an empty array

<b>What is the expected output? What do you see instead?</b>

The expected would be, that the created disrupter behaves normally, i.e. calls the event handler callback for each element, published into the ring buffer. Instead, we see that elements seem to be either overwritten (current assumption) or dispatched in the wrong order..

<b>What version of the product are you using? On what operating system?</b>

Latest Java 2.6 release on Windows XP.

<b>Please provide any additional information below.</b>

Attached, please find a little test driver able to  reproduce the problem. The code simply instantiates a new ring buffer with 128 elements. A producer then pumps 10'000'000 events (simple integer wrappers) into the buffer, and the registered EventHandler just verifies that the elements are delivered to the callback in order.

If the disrupto was created using 

disruptor.handleEventsWith(myHandler);

everything is fine. If, however, it is created with 

disruptor.handleEventsWith(myHandler).then(new EventHandler[0]);

it does not behave properly anymore.

I know, passing an empty array is strange. However, I think the API should be able to handle that situation. Either by throwing an IllegalArgumentException or - IMHO the preferred solution - by simply not doing anything. 

I would prefer the latter approach, since I think it is nicer in the context of the DSL like API of the Disruptor class. In my eyes the example above would then read something like &quot;Instantiate the Disruptor, handle events with my handler and then don't do anything&quot;

Someone intrest this result?

This is some result abount OnePublisherToOneProcessorRawBatchThroughputTest
Run 0, Disruptor=806,451,612 ops/sec
Run 1, Disruptor=821,018,062 ops/sec
Run 2, Disruptor=1,122,964,626 ops/sec
Run 3, Disruptor=1,164,144,353 ops/sec
Run 4, Disruptor=1,133,144,475 ops/sec
Run 5, Disruptor=1,186,239,620 ops/sec
Run 6, Disruptor=1,175,088,131 ops/sec
Run 7, Disruptor=1,143,510,577 ops/sec
Run 8, Disruptor=1,174,398,120 ops/sec
Run 9, Disruptor=1,153,402,537 ops/sec
Run 10, Disruptor=1,154,068,090 ops/sec
Run 11, Disruptor=1,175,088,131 ops/sec
Run 12, Disruptor=1,133,144,475 ops/sec
Run 13, Disruptor=1,049,868,766 ops/sec
Run 14, Disruptor=1,094,690,749 ops/sec
Run 15, Disruptor=1,164,144,353 ops/sec
Run 16, Disruptor=1,186,239,620 ops/sec
Run 17, Disruptor=1,219,512,195 ops/sec
Run 18, Disruptor=1,207,729,468 ops/sec
Run 19, Disruptor=1,196,888,090 ops/sec
In my memory, the best result I saw, is 1,500M o/s, just by some try
//mybusyspin
Run 0, Disruptor=1,583,531,274 ops/sec
Run 1, Disruptor=1,454,545,454 ops/sec
Run 2, Disruptor=1,803,426,510 ops/sec
Run 3, Disruptor=1,728,608,470 ops/sec
Run 4, Disruptor=1,777,777,777 ops/sec
Run 5, Disruptor=1,728,608,470 ops/sec
Run 6, Disruptor=1,908,396,946 ops/sec
Run 7, Disruptor=1,754,385,964 ops/sec
Run 8, Disruptor=1,937,984,496 ops/sec
Run 9, Disruptor=1,706,484,641 ops/sec
Run 10, Disruptor=1,801,801,801 ops/sec
Run 11, Disruptor=1,776,198,934 ops/sec
Run 12, Disruptor=1,855,287,569 ops/sec
Run 13, Disruptor=1,828,153,564 ops/sec
Run 14, Disruptor=1,471,670,345 ops/sec
Run 15, Disruptor=1,801,801,801 ops/sec
Run 16, Disruptor=1,752,848,378 ops/sec
Run 17, Disruptor=1,910,219,675 ops/sec
Run 18, Disruptor=1,828,153,564 ops/sec
Run 19, Disruptor=1,855,287,569 ops/sec

Hahha, this is my new modest-lock, applied for both end
Run 0, Concurrentor=1,644,736,842 ops/sec
Run 1, Concurrentor=1,640,689,089 ops/sec
Run 2, Concurrentor=1,968,503,937 ops/sec
Run 3, Concurrentor=1,968,503,937 ops/sec
Run 4, Concurrentor=1,968,503,937 ops/sec
Run 5, Concurrentor=1,968,503,937 ops/sec
Run 6, Concurrentor=1,998,001,998 ops/sec
Run 7, Concurrentor=1,968,503,937 ops/sec
Run 8, Concurrentor=1,968,503,937 ops/sec
Run 9, Concurrentor=1,968,503,937 ops/sec
Run 10, Concurrentor=2,000,000,000 ops/sec
Run 11, Concurrentor=1,968,503,937 ops/sec
Run 12, Concurrentor=1,968,503,937 ops/sec
Run 13, Concurrentor=1,968,503,937 ops/sec
Run 14, Concurrentor=1,968,503,937 ops/sec
Run 15, Concurrentor=2,000,000,000 ops/sec
Run 16, Concurrentor=2,000,000,000 ops/sec
Run 17, Concurrentor=2,000,000,000 ops/sec
Run 18, Concurrentor=1,968,503,937 ops/sec
Run 19, Concurrentor=1,968,503,937 ops/sec

so, does it have some xxx?

Disruptor DSL not working with SequenceReportingEventHandler [moved]

This is Issue 9 moved from a Google Code project.
Added by 2011-09-12T19:57:18.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

Calling disruptor.handleEventsWith(aSequenceReportingEventHandler) does not call the correct BatchEventProcessor constructor.
This problem is caused by Java's static binding for overloaded methods/constructors.

The temporary solution was to replace line 254 of Disruptor.java with this...

            final BatchEventProcessor<T> batchEventProcessor;
            if (eventHandler instanceof SequenceReportingEventHandler) {
                batchEventProcessor = new BatchEventProcessor<T>(ringBuffer, barrier, (SequenceReportingEventHandler)eventHandler);
            }else{
                batchEventProcessor = new BatchEventProcessor<T>(ringBuffer, barrier, eventHandler);
            }

Not sure if there is a better way.

Lost Data Enqueueing [moved]

This is Issue 15 moved from a Google Code project.
Added by 2011-12-30T00:32:58.000Z by matt.fowles.
Please review that bug for more context and additional comments, but update this bug.
Closed (WontFix).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>
1. import the attached project
2. Run the junit test RingBufferSequencerTest

<b>What is the expected output? What do you see instead?</b>

testStress() is an infinite loop which reruns ones of the earlier tests.  As such it should just loop indefinitely without ever failing.  I see it failing in < 30 seconds on most machines.


<b>What version of the product are you using? On what operating system?</b>

Ubuntu 11.04
java version &quot;1.6.0_29&quot;
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode)

Mac OSX Lion (10.7.2)
java version &quot;1.6.0_29&quot;
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode

oots@eiji:~/dev/disruptor$ svn info
Path: .
URL: http://disruptor.googlecode.com/svn/trunk
Repository Root: http://disruptor.googlecode.com/svn
Repository UUID: be888e01-df2f-7007-e4fb-9ed1888b3550
Revision: 512
Node Kind: directory
Schedule: normal
Last Changed Author: [email protected]
Last Changed Rev: 498
Last Changed Date: 2011-12-18 07:28:32 -0500 (Sun, 18 Dec 2011)

Disruptor Proxy

Hi,

Is it possible to improve and include this as part of the main distribution?

S

SingleThreadedClaimStrategy can go into a state where it does not block even if the ring is full [moved]

This is Issue 27 moved from a Google Code project.
Added by 2012-08-10T08:33:23.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

<b>What steps will reproduce the problem?</b>
1. Create a RingBuffer with SingleThreadedClaimStrategy and a SequenceGroup as the GatingSequence
2. Publish a value to the ring
3. Create a BatchEventProcessor with a slow EventHandler, and add the sequence to the SequenceGroup
4. Start publishing loads of elements

<b>What is the expected output? What do you see instead?</b>

The publishing should be blocked when the it has filled out the whole ring.

The publishing continues without and regards to the added sequence.


<b>What version of the product are you using? On what operating system?</b>
2.10.1 with java 1.7.4 on Windows 7

<b>Please provide any additional information below.</b>

Having checked the code, the problem seems to be a combination of the fact that the SequenceGroup returns Long.MAX_VALUE when no sequences are present and that the waitForFreeSlotAt stores the returned value in minGatingSequence, thus in effect disables that method.

I originally saw the issue by first adding one Processor removing it and the adding a new, while publishing to the ring, but the steps mentioned above should be sufficient to reproduce the problem.

unsupport jdk1.5 [moved]

This is Issue 28 moved from a Google Code project.
Added by 2012-08-28T10:01:25.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Done).

Original labels: Type-Defect, Priority-Medium

Original description

unsupport jdk1.5 ? 

What's the meaning of โ€˜processedSequence'?

Workerpool .java has a code
@OverRide
public void run()
{

    boolean processedSequence = true;
    long nextSequence = sequence.get();
    T event = null;
    while (true)
    {
        try
        {
            if (processedSequence)

What's the meaning of โ€˜processedSequence'?

thank you!

Add thousand separators to perf test results [moved]

This is Issue 8 moved from a Google Code project.
Added by 2011-09-06T17:25:01.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

On line 50 of AbstractPerfTestQueueVsDisruptor.java,
please add a comma to the format to print out thousand separators.

e.g. BlockingQueues=%,d, Disruptor=%,d

Remove all IDE specific artifacts from source code control [moved]

This is Issue 11 moved from a Google Code project.
Added by 2011-09-20T14:35:15.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Defect, Priority-Medium

Original description

Files such as *.iml, *.ipr, and *.iws are Intellij specific files that may contain per developer preferences.
These files are not part of the project, strictly speaking, and should not be tracked by version control.

Patch for /trunk/code/.project [moved]

This is Issue 3 moved from a Google Code project.
Added by 2011-07-19T21:50:08.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Fixed).

Original labels: Type-Patch

Original description

Changes the name of the eclipse project from &quot;distruptor&quot; to &quot;disruptor&quot;.

Gradle Build Support [moved]

This is Issue 4 moved from a Google Code project.
Added by 2011-07-28T14:14:10.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Closed (Invalid).

Original labels: Priority-Medium, Type-Enhancement

Original description

Patch attached to add support for building via Gradle. This could be extended to handle publishing to a Maven repository if there was any interest in avoiding Maven at all costs :)

gradle eclipse - setup Eclipse project config
gradle idea - setup IntelliJ IDEA project config
gradle jar - compile, test and put jar in build/libs
gradle perfTest - compile and run the perf tests
gradle task - list all other available build tasks

Note that the auto-bootstrapping feature of gradle is configured in this patch but the wrapper is not included as it involves a small binary .jar. To generate the wrapper run and commit the results of:

gradle wrapper

A developer can then build the app or configure it for their IDE without having Gradle (or Ant) installed by running:

./gradlew <task>

What is the correct way to add/remove handlers dynamically?

Hello, I have the situation when I need dynamically add and remove handlers.
My code looks like the this:

addHandler(EventHandler handler) {
    SequenceBarrier barrier = ringBuffer.newBarrier();
    BatchEventProcessor processor = new BatchEventProcessor(ringBuffer, barrier, handler);
    processor.getSequence().set(barrier.getCursor());
    sequenceGroup.add(batchEventProcessor.getSequence());
    processor.getSequence().set(ringBuffer.getCursor());
    processor.run();
}

removeHandler(BatchEventProcessor processor) {
    processor.halt();
    sequenceGroup.remove(processor.getSequence());
} 

Is this a correct setup?

I'm asking this because very rarely I'm getting the following exception on handler removal:
java.lang.ArrayIndexOutOfBoundsException: 0
at com.lmax.disruptor.SequenceGroup.remove(SequenceGroup.java:116)
at removeHandler()

and I was not able to find the issue for now :(

Using disruptor 2.10.3 with java 1.7.3 on Windows 7 x64.

Thanks in advance!

WorkHandler does not TAKE messages from the RingBuffer in FIFO order.

Environment Test run on Intel i7 Quad 2.2Ghz 8GB with OS-X 10.8.3
Libraries Java JDK 1.7.0_21-b12 and disruptor-3.0.1.jar

Test Case

My intention is to use the Disruptor to build a work dispatcher with back-pressure, so Producers don't outpace Consumers (Workers). The Dispatcher will use the RingBuffer to route the producers Message object to a Worker for processing. There is a 1:1 relationship between a Message and a Worker. That is, a Message instance should be processed BY ONLY ONE Worker.

My assumption is the RingBuffer and WorkerHandler (called by WorkProcessor) when configured correctly should support this use case, but I cannot make it happen or is it a bug!

In order to decifer this issue, the test case code below publishes 8 messages to a RingBuffer whose size is 4. The small buffer size is intentional to log and interpret the ring buffers behaviour.

Issues

See DispatcherTest test cases testOnePublisherOneConsumers and testOnePublisherMultipleConsumers.

1) The Worker handler MessageWorkerHandler does not TAKE the message from the RingBuffer. but instead READS the message from the ring buffer. Maybe I'm wrong here, but one would expected the worker handler to TAKE the message by default, therefore being inline with the master-worker pattern.

2) The Worker handler sometimes did not receive Message's from the RingBuffer in published FIFO order.

3) If the RingBuffer size is 4, and there are 8 unique Messages published to the RingBuffer,

3.1) then for testOnePublisherOneConsumers, the Worker 1 below should receive Message instance with id 1 to 8 in FIFO order, but instead it receives twice instance with id 5 to 8 usually in NON-FIFO order (although in the test case execution below it was FIFO order).

---Test: 1 Publisher, 1 Consumer (Worker)-------------------
Worker[0] consumed [1] Message where Message[id: 5, instance: test.Message@e8e8f9].
Worker[0] consumed [2] Message where Message[id: 6, instance: test.Message@1176e5f].
Worker[0] consumed [3] Message where Message[id: 7, instance: test.Message@14f2bd7].
Worker[0] consumed [4] Message where Message[id: 8, instance: test.Message@c759f5].
Worker[0] consumed [5] Message where Message[id: 5, instance: test.Message@e8e8f9].
Worker[0] consumed [6] Message where Message[id: 6, instance: test.Message@1176e5f].
Worker[0] consumed [7] Message where Message[id: 7, instance: test.Message@14f2bd7].
Worker[0] consumed [8] Message where Message[id: 8, instance: test.Message@c759f5].
Finished: Dispatcher dispatched [8] Messages to [1] Worker(s). Worker(s) consumed [8] Messages.

In this case I assume the Worker (WorkProcess.run() --> WorkHandler) should have TAKEN the message from the ring, but instead it only READS it. Is my assumption correct or did I miss understand the documentation?

3.2) then for testOnePublisherMultipleConsumers, Worker 1 should receive 4 unique Messages in FIFO order, and Worker 2 should receive THE OTHER 4 unique messages in FIFO order. But instead both Workers receive twice instance 5, 6, 7 and 8 in NON-FIFO order.

---Test: 1 Publisher, 2 Consumers (Workers)-------------------
Worker[1] consumed [1] Message where Message[id: 6, instance: test.Message@14f2bd7].
Worker[0] consumed [1] Message where Message[id: 5, instance: test.Message@14f2bd7].
Worker[1] consumed [2] Message where Message[id: 7, instance: test.Message@c759f5].
Worker[0] consumed [2] Message where Message[id: 8, instance: test.Message@1e2f6b0].
Worker[1] consumed [3] Message where Message[id: 5, instance: test.Message@14f2bd7].
Worker[0] consumed [3] Message where Message[id: 6, instance: test.Message@14f2bd7].
Worker[1] consumed [4] Message where Message[id: 7, instance: test.Message@c759f5].
Worker[0] consumed [4] Message where Message[id: 8, instance: test.Message@1e2f6b0].
Finished: Dispatcher dispatched [8] Messages to [2] Worker(s). Worker(s) consumed [8] Messages.

Again in this test case I assume the Worker (WorkProcess.run() --> WorkHandler) should have TAKEN the message from the ring, but instead it only READS it. So, Worker 1 and 2 end up processing the same unique Messages, when they should not. Is my assumption correct or did I miss understand the documentation?

Summary

For both test cases - where the RingBuffer size being 4 - the method Dispatcher.publish() is called 8 times. My assumption here is that ringBuffer.tryNext(); as documented should throw a InsufficientCapacityException exception when trying to publish Messages 5,6,7 and 8, as Message 1,2,3 and 4 have not yet been consumed by a Worker. But instead no exception is thrown and 5,6,7 and 8 overwrite 1,2,3 and 4.

Test Source Code

NOTE: The code below does not use the Disruptor DSL. I also tried it with the DSL, but had the same issues.

DispatcherTest.java

package test;

import static org.junit.Assert.assertEquals;
import org.junit.Test;

/**
 * TEST CASE: Use Disruptor to build a work dispatcher with back-pressure, so Producers don't 
 * outpace Consumers (Workers).
 * TEST ISSUE: The Disruptor WorkerHandler do not receive the Messages in FIFO order from
 * the RingBuffer, but instead in LIFO order.
 * 
 * The Dispatcher will use the RingBuffer to route the producer Message object to a Worker for
 * processing. Their is a 1:1 relationship between a Message and a Worker - that is a Message
 * instance should be processed by only one Worker.
 * 
 * Test 1: Single Producer, Single Consumer (Worker).
 *                                         |-------------| 
 *     Producer (Message) --- publish ---> | RING BUFFER | --- take --->  Worker (Message)  
 *                                         |-------------|
 * 
 * Test 2: Single Producer, Multiple Consumers (Workers)
 * 
 *                                         |-------------| --- take --->  Worker 1 (Message) 
 *     Producer (Message) --- publish ---> | RING BUFFER |  
 *                                         |-------------| --- take --->  Worker n+1 (Message) 
 * 
 * @since 06 May 2013 12:11:29
 */
public class DispatcherTest {
    @Test
    public void testOnePublisherOneConsumer() throws InterruptedException{
        int workers        = 1;
        int ringBufferSize = 2;  
        int iterations     = 8;

        log("Test: 1 Publisher, 1 Consumers (Workers)");

        Dispatcher dispatcher = new Dispatcher(ringBufferSize, workers);

        for(int i=0; i < iterations; i++){
            dispatcher.publish(new Message(i+1));
        }
        Thread.sleep(500);

        long dispatched = dispatcher.getDispatchedCount();
        long consumed   = dispatcher.getConsumedCount();
        log(workers, dispatched, consumed);

        assertEquals(dispatched, iterations);
        assertEquals(consumed, iterations);
    }

    @Test
    public void testOnePublisherMultipleConsumers() throws InterruptedException{
        int workers        = 2;
        int ringBufferSize = 2; // to the power of 2
        int iterations     = 8;

        log("Test: 1 Publisher, 2 Consumers (Workers)");

        Dispatcher dispatcher = new Dispatcher(ringBufferSize, workers);

        for(int i=0; i < iterations; i++){
            dispatcher.publish(new Message(i+1));
        }      
        Thread.sleep(500);

        long dispatched = dispatcher.getDispatchedCount();
        long consumed   = dispatcher.getConsumedCount();
        log(workers, dispatched, consumed);

        assertEquals(dispatched, iterations);
        assertEquals(consumed, iterations);
    }  

    public void log(String title){
        System.out.println("\n--" + title + "--------------------");
    }

    public void log(int workers, long dispatched, long consumed){
        System.out.println("Finished: Dispatcher dispatched [" + dispatched + "] " + 
                "Messages to [" + workers + "] Worker(s). " + 
                "Worker(s) consumed ["+ consumed +"] Messages.\n");   
    }
}

Message.java

package test;

public class Message {
    private int id;

    public Message(){}
    public Message(int id)   { this.id = id; }

    public void setId(int id){ this.id = id; }
    public int  getId()      { return id;    } 
}

Dispatcher.java

package test;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.FatalExceptionHandler;
import com.lmax.disruptor.InsufficientCapacityException;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.WorkHandler;
import com.lmax.disruptor.WorkerPool;
import com.lmax.disruptor.YieldingWaitStrategy;

/**
 * Use Disruptor to build a work dispatcher with back-pressure, so Producers don't outpace 
 * Consumers (Workers).
 * The Dispatcher will use the RingBuffer to route the producer Message object to a Worker for
 * processing. Their is a 1:1 relationship between a Message and a Worker - that is a Message
 * instance should be processed by only one Worker.
 * 
 * @since 07 May 2013 12:11:29
 */
public class Dispatcher {
  private RingBuffer<Message> ringBuffer;
  private final WorkerPool<Message> workerPool;

  private final MessageWorkerHandler[] schedulers;   
  private final EventFactory<Message> EVENT_FACTORY = new MessageEventFactory();

  private long dispatched = 0;

  public class MessageWorkerHandler implements WorkHandler<Message>{
    private int  id = 0;
    private long consumed = 0;

    public MessageWorkerHandler(int id){
      this.id = id;       
    }

    @Override
    public void onEvent(Message event) throws Exception {
      consumed++;
      System.out.println("Worker[" + id + "] consumed [" + consumed + "] Message " + 
                         "where Message[id: " + event.getId() + ", instance: " + event + "].");

      // DO WORK HERE...
    }

    public long getEventsConsumed() {
      return consumed;
    } 
  }

  public class MessageEventFactory implements EventFactory<Message> {
    public MessageEventFactory(){};

    public Message newInstance(){
      return new Message();
    }
  };

  public Dispatcher(int ringBufferSize, int workerSize){

    ringBuffer = RingBuffer.createSingleProducer(EVENT_FACTORY, 
            ringBufferSize,
            new YieldingWaitStrategy());

    schedulers = new MessageWorkerHandler[workerSize];
    for(int i=0; i < workerSize; i++){
        schedulers[i] = new MessageWorkerHandler(i);
    }

    workerPool = new WorkerPool<Message>(ringBuffer,
          ringBuffer.newBarrier(),
          new FatalExceptionHandler(),
          schedulers );

    Executor executor = Executors.newFixedThreadPool(workerSize);
    workerPool.start(executor);        
  }

  public boolean publish(Message message){
    while(true){
      try{
        final long sequence = ringBuffer.tryNext();
        ringBuffer.get(sequence).setId(message.getId());
        ringBuffer.publish(sequence);
        dispatched++;
        return true;
      }catch(InsufficientCapacityException e){
        waitForSlot();
        continue;
      }
    }
  }

  public long getDispatchedCount(){
    return dispatched;
  }

  public long getConsumedCount(){
    long consumed = 0;
    for(int i=0; i < schedulers.length; i++){
      consumed += schedulers[i].getEventsConsumed();
    }
    return consumed;
  }

  private void waitForSlot(){
    try {
      Thread.sleep(50);
    } catch (InterruptedException e1) {
      e1.printStackTrace();
    }       
  }

  public void clear(){
    workerPool.drainAndHalt();
  }        
}

Build tests failing

Hi,
I'm trying to build disruptor on Win 7 64 bit. I'm using ConEmu as the terminal. When I run ./gradlew I get the following errors:
com.lmax.disruptor.dsl.DisruptorTest > shouldSupportCustomProcessorsAsDependencies FAILED
java.lang.AssertionError at DisruptorTest.java:67

com.lmax.disruptor.dsl.DisruptorTest > shouldProvideEventsToWorkHandlers FAILED
java.lang.AssertionError at DisruptorTest.java:67

114 tests completed, 2 failed
:test FAILED

I tried this with jdk1.6.0_29 and jdk1.7.0_17 and got the same errors both times. Is this simply a limitation in Windows or something else?

Thanks for your help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.