Skip to content

Commit

Permalink
Add performance tests for custom immutable ring buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeb01 committed Dec 3, 2013
1 parent 82e4a12 commit c1f8a57
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ pom.xml
*.iml
*.ipr
*.iws
*-gc.log
26 changes: 26 additions & 0 deletions runme.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

rm *-gc.log

echo "Running Simple..."
$JAVA_HOME/bin/java -Xloggc:simple-gc.log \
-verbose:gc \
-XX:+PrintGCDateStamps \
-XX:+PrintGCApplicationStoppedTime \
-cp "build/classes/main:build/classes/perf:templib/*.jar" \
com.lmax.disruptor.immutable.SimplePerformanceTest
echo "Done"

grep 'stopped:' simple-gc.log | sed 's/.*stopped: \([0-9.]*\) seconds/\1/' | sort -n | awk '{ printf "%1.3f\n", $1 }' | (echo " Count Millis" ; uniq -c )

echo "Running Custom..."
$JAVA_HOME/bin/java -Xloggc:custom-gc.log \
-verbose:gc \
-XX:+PrintGCDateStamps \
-XX:+PrintGCApplicationStoppedTime \
-cp "build/classes/main:build/classes/perf:templib/*.jar" \
com.lmax.disruptor.immutable.CustomPerformanceTest
echo "Done"

grep 'stopped:' custom-gc.log | sed 's/.*stopped: \([0-9.]*\) seconds/\1/' | sort -n | awk '{ printf "%1.3f\n", $1 }' | (echo " Count Millis" ; uniq -c )

7 changes: 7 additions & 0 deletions src/perftest/java/com/lmax/disruptor/immutable/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.lmax.disruptor.immutable;

public class Constants
{
public static final long ITERATIONS = 1000 * 1000 * 100L;
public static final int SIZE = 1 << 20;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.lmax.disruptor.immutable;

import java.util.concurrent.locks.LockSupport;

import com.lmax.disruptor.BatchEventProcessor;
import com.lmax.disruptor.SingleProducerSequencer;
import com.lmax.disruptor.YieldingWaitStrategy;

public class CustomPerformanceTest
{
private final CustomRingBuffer<SimpleEvent> ringBuffer;

public CustomPerformanceTest()
{
ringBuffer = new CustomRingBuffer<SimpleEvent>(new SingleProducerSequencer(Constants.SIZE, new YieldingWaitStrategy()));
}

public void run()
{
try
{
doRun();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}

private void doRun() throws InterruptedException
{
BatchEventProcessor<?> batchEventProcessor = ringBuffer.createHandler(new SimpleEventHandler());

Thread t = new Thread(batchEventProcessor);
t.start();

long iterations = Constants.ITERATIONS;
for (long l = 0; l < iterations; l++)
{
SimpleEvent e = new SimpleEvent(l, l, l, l);
ringBuffer.put(e);
}

while (batchEventProcessor.getSequence().get() != iterations - 1)
{
LockSupport.parkNanos(1);
}

batchEventProcessor.halt();
t.join();
}

public static void main(String[] args)
{
new CustomPerformanceTest().run();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.lmax.disruptor.immutable;

import com.lmax.disruptor.BatchEventProcessor;
import com.lmax.disruptor.DataProvider;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.LifecycleAware;
import com.lmax.disruptor.Sequencer;

public class CustomRingBuffer<T> implements DataProvider<EventAccessor<T>>, EventAccessor<T>
{
private static final class AccessorEventHandler<T> implements EventHandler<EventAccessor<T>>, LifecycleAware
{
private final EventHandler<T> handler;
private final LifecycleAware lifecycle;

private AccessorEventHandler(EventHandler<T> handler)
{
this.handler = handler;
lifecycle = handler instanceof LifecycleAware ? (LifecycleAware) handler : null;
}

@Override
public void onEvent(EventAccessor<T> accessor, long sequence, boolean endOfBatch) throws Exception
{
this.handler.onEvent(accessor.take(sequence), sequence, endOfBatch);
}

@Override
public void onShutdown()
{
if (null != lifecycle)
{
lifecycle.onShutdown();
}
}

@Override
public void onStart()
{
if (null != lifecycle)
{
lifecycle.onStart();
}
}
}

private final Sequencer sequencer;
private final Object[] buffer;
private final int mask;

public CustomRingBuffer(Sequencer sequencer)
{
this.sequencer = sequencer;
buffer = new Object[sequencer.getBufferSize()];
mask = sequencer.getBufferSize() - 1;
}

private int index(long sequence)
{
return (int) sequence & mask;
}

public void put(T e)
{
long next = sequencer.next();
buffer[index(next)] = e;
sequencer.publish(next);
}

@SuppressWarnings("unchecked")
@Override
public T take(long sequence)
{
int index = index(sequence);

T t = (T) buffer[index];
buffer[index] = null;

return t;
}

@Override
public EventAccessor<T> get(long sequence)
{
return this;
}

public BatchEventProcessor<EventAccessor<T>> createHandler(final EventHandler<T> handler)
{
BatchEventProcessor<EventAccessor<T>> processor =
new BatchEventProcessor<EventAccessor<T>>(this,
sequencer.newBarrier(),
new AccessorEventHandler<T>(handler));
sequencer.addGatingSequences(processor.getSequence());

return processor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.lmax.disruptor.immutable;

public interface EventAccessor<T>
{
T take(long sequence);
}
18 changes: 18 additions & 0 deletions src/perftest/java/com/lmax/disruptor/immutable/EventHolder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.lmax.disruptor.immutable;

import com.lmax.disruptor.EventFactory;

public class EventHolder
{

public static final EventFactory<EventHolder> FACTORY = new EventFactory<EventHolder>()
{
@Override
public EventHolder newInstance()
{
return new EventHolder();
}
};

public SimpleEvent event;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.lmax.disruptor.immutable;

import com.lmax.disruptor.EventHandler;

public class EventHolderHandler implements EventHandler<EventHolder>
{
private final EventHandler<SimpleEvent> delegate;

public EventHolderHandler(EventHandler<SimpleEvent> delegate)
{
this.delegate = delegate;
}

@Override
public void onEvent(EventHolder holder, long sequence, boolean endOfBatch) throws Exception
{
delegate.onEvent(holder.event, sequence, endOfBatch);
holder.event = null;
}
}
22 changes: 22 additions & 0 deletions src/perftest/java/com/lmax/disruptor/immutable/SimpleEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.lmax.disruptor.immutable;

public class SimpleEvent
{
private final long id;
private final long v1;
private final long v2;
private final long v3;

public SimpleEvent(long id, long v1, long v2, long v3)
{
this.id = id;
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
}

public long getCounter()
{
return v1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.lmax.disruptor.immutable;

import com.lmax.disruptor.EventHandler;

public class SimpleEventHandler implements EventHandler<SimpleEvent>
{
@Override
public void onEvent(SimpleEvent arg0, long arg1, boolean arg2) throws Exception
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.lmax.disruptor.immutable;

import java.util.concurrent.locks.LockSupport;

import com.lmax.disruptor.BatchEventProcessor;
import com.lmax.disruptor.EventTranslatorOneArg;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;

public class SimplePerformanceTest
{
private final RingBuffer<EventHolder> ringBuffer;
private final EventHolderHandler eventHolderHandler;

public SimplePerformanceTest()
{
ringBuffer = RingBuffer.createSingleProducer(EventHolder.FACTORY, Constants.SIZE, new YieldingWaitStrategy());
eventHolderHandler = new EventHolderHandler(new SimpleEventHandler());
}

public void run()
{
try
{
doRun();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}

private void doRun() throws InterruptedException
{
BatchEventProcessor<EventHolder> batchEventProcessor =
new BatchEventProcessor<EventHolder>(ringBuffer,
ringBuffer.newBarrier(),
eventHolderHandler);
ringBuffer.addGatingSequences(batchEventProcessor.getSequence());

Thread t = new Thread(batchEventProcessor);
t.start();

long iterations = Constants.ITERATIONS;
for (long l = 0; l < iterations; l++)
{
SimpleEvent e = new SimpleEvent(l, l, l, l);
ringBuffer.publishEvent(TRANSLATOR, e);
}

while (batchEventProcessor.getSequence().get() != iterations - 1)
{
LockSupport.parkNanos(1);
}

batchEventProcessor.halt();
t.join();
}

private static final EventTranslatorOneArg<EventHolder, SimpleEvent> TRANSLATOR =
new EventTranslatorOneArg<EventHolder, SimpleEvent>()
{
@Override
public void translateTo(EventHolder holder, long arg1, SimpleEvent event)
{
holder.event = event;
}
};

public static void main(String[] args)
{
new SimplePerformanceTest().run();
}
}

0 comments on commit c1f8a57

Please sign in to comment.