- Timestamp:
- 12/10/13 17:39:29 (8 years ago)
- Location:
- Tests/JAVA/logger
- Files:
-
- 18 added
- 1 deleted
- 13 edited
- 2 copied
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
Tests/JAVA/logger/scripts/batch.sh
r593 r594 3 3 for PAYLOAD in 0 20 40 60 80 120 200 4 4 do 5 java -server -Xmx512M -da -Dwriter-backoff=$PAYLOAD -Dcells-per-record= 32 -jar target/benchmarks.jar ".*$1.*" -f -w 2 -wi 5 -i 5 -r 5-gc true >> "data/$1.results"5 java -server -Xmx512M -da -Dwriter-backoff=$PAYLOAD -Dcells-per-record=8 -jar target/benchmarks.jar ".*$1.*" -f -w 2 -wi 5 -i 5 -r 10 -gc true >> "data/$1.results" 6 6 done 7 8 #for CELLS in 4 8 16 32 63 9 #do 10 # java -server -Xmx512M -da -Dwriter-backoff=80 -Dcells-per-record=$CELLS -jar target/benchmarks.jar ".*$1.*" -f -w 2 -wi 5 -i 5 -r 10 -gc true >> "data/$1.cells.results" 11 #done -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/PlaygroundMain.java
r589 r594 5 5 import java.util.concurrent.TimeUnit; 6 6 7 import com.db.logger.api.impl.logger. CircularBuffer;8 import com.db.logger.api.impl.logger. DemultiplexingSequencer;7 import com.db.logger.api.impl.logger.RingBuffer; 8 import com.db.logger.api.impl.logger.MCSDSequencer; 9 9 import com.db.logger.api.impl.logger.formatters.SimpleLogMessage; 10 10 import com.db.logger.api.impl.logger.buffer.PlainLongsBuffer; … … 32 32 final int length = ( 1 << 14 ); 33 33 final PlainLongsBuffer buffer = new PlainLongsBuffer( length ); 34 final DemultiplexingSequencer sequencer = new DemultiplexingSequencer( length );34 final MCSDSequencer sequencer = new MCSDSequencer( length ); 35 35 36 36 final int workers = Runtime.getRuntime().availableProcessors() - 1; … … 41 41 public void run() { 42 42 for(; ; ) { 43 sequencer.drainTo( new DemultiplexingSequencer.Drainer() {43 sequencer.drainTo( new MCSDSequencer.Drainer() { 44 44 @Override 45 45 public int available( final long startSequence, … … 58 58 formatId, 59 59 2, 60 new CircularBuffer( sequencer, buffer, SPINNING )60 new RingBuffer( sequencer, buffer, SPINNING ) 61 61 ); 62 62 workersPool.submit( -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/FastLoggerImpl.java
r590 r594 9 9 import com.db.logger.api.LogMessage; 10 10 import com.db.logger.api.impl.logger.buffer.ILongsBuffer; 11 import com.db.logger.api.impl.logger.formatters.FlyweightLogMessage;12 11 import com.db.logger.api.impl.logger.formatters.RawLogMessage; 13 12 import com.db.logger.api.impl.logger.formatters.SimpleLogMessage; … … 31 30 private final ThreadFactory threadFactory; 32 31 33 private final CircularBuffer circularBuffer;32 private final RingBuffer ringBuffer; 34 33 35 34 private final RawWriter writer; … … 49 48 50 49 final int length = buffer.length(); 51 this. circularBuffer = new CircularBuffer(52 new DemultiplexingSequencer( length ),50 this.ringBuffer = new RingBuffer( 51 new MCSDSequencer( length ), 53 52 buffer, 54 53 waitingStrategy … … 72 71 messageInfo.formatId, 73 72 messageInfo.argumentsCount, 74 circularBuffer73 ringBuffer 75 74 ); 76 75 } … … 79 78 @Override 80 79 protected RawLogMessage initialValue() { 81 return new RawLogMessage( circularBuffer );80 return new RawLogMessage( ringBuffer ); 82 81 } 83 82 }; … … 91 90 } 92 91 93 private final THashMap<String, MessageInfo> formats = new THashMap<String, MessageInfo>( 128 ); 92 private final MessagesCatalog messages = new MessagesCatalog( 2048 ); 93 94 public MessageInfo lookupMessageInfo( final String messageFormat ) { 95 return messages.lookupMessageInfo( messageFormat ); 96 } 94 97 95 98 public LogMessage message( final String messageFormat ) { … … 99 102 } 100 103 101 public MessageInfo lookupMessageInfo( final String messageFormat ) {102 //TODO RC: dcl, ok for testing, but needs rewrite103 MessageInfo messageInfo = formats.get( messageFormat );104 if( messageInfo == null ) {105 synchronized( formats ) {106 messageInfo = formats.get( messageFormat );107 if( messageInfo == null ) {108 checkArgument( messageFormat != null, "messageFormat can't be null" );109 messageInfo = new MessageInfo(110 messageFormat,111 calculateArgumentsCount( messageFormat ),112 formats.size() + 1113 );114 formats.put( messageFormat, messageInfo );115 }116 }117 }118 return messageInfo;119 }120 121 private static int calculateArgumentsCount( final String formatMessage ) {122 int argumentsCount = 0;123 for( int i = 0; i < formatMessage.length(); i++ ) {124 if( formatMessage.charAt( i ) == '%' ) {//TODO RC: not safe! '%%' is not placeholder125 argumentsCount++;126 }127 }128 return argumentsCount;129 }130 131 104 private Thread drainerThread = null; 132 105 … … 134 107 if( drainerThread == null ) { 135 108 final Drainer drainer = new Drainer( 136 circularBuffer, new ConsumingDrainer(137 circularBuffer.buffer(),109 ringBuffer, new ConsumingDrainer( 110 ringBuffer.buffer(), 138 111 writer 139 112 ) … … 165 138 // } 166 139 167 private static class Drainer implements Runnable, DemultiplexingSequencer.Drainer {140 private static class Drainer implements Runnable, MCSDSequencer.Drainer { 168 141 //TODO setup! 169 142 private static final int MIN_PERIOD_MS = 1; … … 173 146 174 147 private final ConsumingDrainer consumer; 175 private final CircularBuffer circularBuffer;176 177 private Drainer( final CircularBuffer circularBuffer,148 private final RingBuffer ringBuffer; 149 150 private Drainer( final RingBuffer ringBuffer, 178 151 final ConsumingDrainer consumer ) { 179 152 this.consumer = consumer; 180 this. circularBuffer = circularBuffer;153 this.ringBuffer = ringBuffer; 181 154 } 182 155 … … 185 158 while( !Thread.interrupted() ) { 186 159 try { 187 circularBuffer.sequencer().drainTo( this );188 189 reportingPeriodMs = nextWaitPeriod(190 processedRecords,191 circularBuffer.length(),192 reportingPeriodMs193 );160 ringBuffer.drainTo( this ); 161 Thread.yield(); 162 // reportingPeriodMs = nextWaitPeriod( 163 // processedRecords, 164 // ringBuffer.length(), 165 // reportingPeriodMs 166 // ); 194 167 // Thread.sleep( reportingPeriodMs ); 195 168 // } catch( InterruptedException e ) { … … 231 204 } 232 205 233 private static class ConsumingDrainer implements DemultiplexingSequencer.Drainer {206 private static class ConsumingDrainer implements Sequencer.Drainer { 234 207 private static final int SPINS_PER_TURN = 256; 235 208 -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/MCSDSequencer.java
r589 r594 1 1 package com.db.logger.api.impl.logger; 2 2 3 import java.lang.reflect.Field;4 5 import sun.misc.Unsafe;6 7 import static com.google.common.base.Preconditions.checkArgument;8 import static com.google.common.base.Preconditions.checkState;9 3 10 4 /** … … 16 10 * Client code must involve some kind of protocol to ensure that entry filling with 17 11 * data was finished, since sequencer itself takes responsibility only on spreading 18 * indexes to producers. {@link #drainTo( com.db.logger.api.impl.logger.DemultiplexingSequencer.Drainer)}12 * indexes to producers. {@link #drainTo(MCSDSequencer.Drainer)} 19 13 * will supply all indexes which was given by {@link #claim} at moment, 20 14 * but not all of associated records are full with data. You need some kind of flag … … 24 18 * created 7/4/12 at 3:54 PM 25 19 */ 26 public class DemultiplexingSequencer { 27 public static final long INVALID_INDEX = -1L; 20 public class MCSDSequencer extends Sequencer { 28 21 29 private static final Unsafe UNSAFE = UnsafeHelper.unsafe(); 30 private static final long HEAD_OFFSET; 31 private static final long TAIL_OFFSET; 32 33 static { 34 try { 35 final Field headCursorField = DemultiplexingSequencer.class.getDeclaredField( "headCursor" ); 36 final Field tailCursorField = DemultiplexingSequencer.class.getDeclaredField( "tailCursor" ); 37 HEAD_OFFSET = UNSAFE.objectFieldOffset( headCursorField ); 38 TAIL_OFFSET = UNSAFE.objectFieldOffset( tailCursorField ); 39 final long padding = TAIL_OFFSET - HEAD_OFFSET; 40 if( padding < 64 ) { 41 System.out.println( "Padding is optimized out: " + padding ); 42 } 43 } catch( NoSuchFieldException e ) { 44 throw new RuntimeException( e ); 45 } 22 public MCSDSequencer( final int length ) { 23 super( length ); 46 24 } 47 25 48 private final int length;49 26 50 /** 51 * Elements range: [headCursor, tailCursor) 52 * <p/> 53 * (tailCursor - headCursor) == elements count 54 * <p/> 55 * 0 <= (tailCursor - headCursor) <= length => state invariant 56 * <p/> 57 * tailCursor - headCursor == length => buffer is full 58 * tailCursor - headCursor == 0 => buffer is empty 59 * <p/> 60 * (headCursor % size ) is the index of first item in buffer 61 * (tailCursor % size ) is the index of _cell_ for _next last item_ 62 */ 63 public volatile long r0, r1, r2, r3, r4, r5, r6, r7; 64 private volatile long headCursor = 0; 65 public volatile long p0, p1, p2, p3, p4, p5, p6, p7; 66 public volatile long q0, q1, q2, q3, q4, q5, q6, q7; 67 private volatile long tailCursor = 0; 68 public volatile long z0, z1, z2, z3, z4, z5, z6, z7; 69 70 public DemultiplexingSequencer( final int length ) { 71 checkArgument( length > 0, "length(%s) must be > 0", length ); 72 checkArgument( ( length & ( length - 1 ) ) == 0, 73 "length %s should be power of 2", length ); 74 75 this.length = length; 76 } 77 78 /** @return -1, if not available */ 79 public long claim() { 80 return claim( 1 ); 81 } 82 83 public long claim( final int size ) { 84 return claim( size, WaitingStrategy.NO_WAIT ); 85 } 86 27 @Override 87 28 public long claim( final int size, 88 29 final WaitingStrategy waitingStrategy ) { … … 102 43 } 103 44 } 104 105 /**106 * It is single-threaded method: it must be called from one thread, or be107 * protected by external mutex.108 */109 public void drainTo( final Drainer drainer ) {110 checkArgument( drainer != null, "drainer can't be null" );111 112 //remember: claimed indexes are all in [headCursor, tailCursor)113 final long firstClaimed = headCursor;114 final long sentinelIndex = tailCursor;115 if( sentinelIndex > firstClaimed ) {116 final long reclaimedIndexes = drainer.available(117 firstClaimed,118 sentinelIndex119 );120 final long maxForReclaim = sentinelIndex - firstClaimed;121 checkState( reclaimedIndexes >= 0 && reclaimedIndexes <= maxForReclaim,122 "Can't reclaim %s indexes: only [0,%s] available",123 reclaimedIndexes, maxForReclaim124 );125 UNSAFE.putOrderedLong( this, HEAD_OFFSET, firstClaimed + reclaimedIndexes );126 }127 }128 129 130 public interface Drainer {131 /**132 * Sequence range [startSequence, sentinelSequence) is claimed by sequencer,133 * and may be reclaimed134 *135 * @return number of sequences reclaimed. I.e [startSequence, startSequence+length]136 * would be available for reuse. Max value allowed to return is137 * (sentinelSequence-startSequence)138 */139 140 public int available( final long startSequence,141 final long sentinelSequence );142 }143 45 } 144 -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/RingBuffer.java
r589 r594 7 7 * created 05.12.13 at 0:41 8 8 */ 9 public final class CircularBuffer {9 public final class RingBuffer { 10 10 private final ILongsBuffer buffer; 11 private final DemultiplexingSequencer sequencer;11 private final Sequencer sequencer; 12 12 private final WaitingStrategy waitingStrategy; 13 13 14 public CircularBuffer( final DemultiplexingSequencer sequencer,15 16 14 public RingBuffer( final Sequencer sequencer, 15 final ILongsBuffer buffer, 16 final WaitingStrategy waitingStrategy ) { 17 17 this.waitingStrategy = waitingStrategy; 18 18 this.sequencer = sequencer; … … 28 28 } 29 29 30 public DemultiplexingSequencer sequencer() { 31 return sequencer; 32 } 33 34 public WaitingStrategy waitingStrategy() { 35 return waitingStrategy; 30 public void drainTo( final Sequencer.Drainer drainer ) { 31 sequencer.drainTo( drainer ); 36 32 } 37 33 38 34 public long claim( final int size ) { 39 return sequencer ().claim(35 return sequencer.claim( 40 36 size, 41 37 waitingStrategy -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/formatters/AbstractLogBuilder.java
r590 r594 2 2 3 3 import com.db.logger.api.FluentLogBuilder; 4 import com.db.logger.api.LogMessage; 5 import com.db.logger.api.impl.logger.CircularBuffer; 4 import com.db.logger.api.impl.logger.RingBuffer; 6 5 import com.db.logger.api.impl.logger.RecordHelper; 7 6 import net.jcip.annotations.NotThreadSafe; 8 7 9 import static com.db.logger.api.impl.logger. DemultiplexingSequencer.INVALID_INDEX;8 import static com.db.logger.api.impl.logger.MCSDSequencer.INVALID_INDEX; 10 9 import static com.db.logger.api.impl.logger.RecordHelper.RecordType.LOG_RECORD; 11 10 import static com.google.common.base.Preconditions.checkArgument; … … 20 19 public static final int NOT_SET = -1; 21 20 22 private final CircularBuffer buffer;21 private final RingBuffer buffer; 23 22 24 23 protected int argumentIndex = NOT_SET; 25 24 protected long position = INVALID_INDEX; 26 25 27 public AbstractLogBuilder( final CircularBuffer buffer ) {26 public AbstractLogBuilder( final RingBuffer buffer ) { 28 27 checkArgument( buffer != null, "buffer can't be null" ); 29 28 this.buffer = buffer; -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/formatters/FlyweightLogMessage.java
r590 r594 2 2 3 3 import com.db.logger.api.LogMessage; 4 import com.db.logger.api.impl.logger. CircularBuffer;4 import com.db.logger.api.impl.logger.RingBuffer; 5 5 import com.db.logger.api.impl.logger.MessageInfo; 6 6 … … 18 18 private MessageInfo messageInfo = null; 19 19 20 public FlyweightLogMessage( final CircularBuffer circularBuffer ) {21 super( circularBuffer );20 public FlyweightLogMessage( final RingBuffer ringBuffer ) { 21 super( ringBuffer ); 22 22 } 23 23 -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/formatters/RawLogMessage.java
r590 r594 3 3 import com.db.logger.api.LogMessage; 4 4 import com.db.logger.api.FluentLogBuilder; 5 import com.db.logger.api.impl.logger. CircularBuffer;5 import com.db.logger.api.impl.logger.RingBuffer; 6 6 import com.db.logger.api.impl.logger.MessageInfo; 7 7 import com.db.logger.api.impl.logger.RecordHelper; 8 8 9 9 import static com.db.logger.api.impl.logger.formatters.AbstractLogBuilder.NOT_SET; 10 import static com.db.logger.api.impl.logger. DemultiplexingSequencer.INVALID_INDEX;10 import static com.db.logger.api.impl.logger.MCSDSequencer.INVALID_INDEX; 11 11 import static com.db.logger.api.impl.logger.RecordHelper.RecordType.LOG_RECORD; 12 12 import static com.google.common.base.Preconditions.checkArgument; … … 19 19 public final class RawLogMessage implements LogMessage, FluentLogBuilder { 20 20 21 private final CircularBuffer buffer;21 private final RingBuffer buffer; 22 22 23 23 private int argumentIndex = NOT_SET; … … 29 29 private int argumentsCount; 30 30 31 public RawLogMessage( final CircularBuffer circularBuffer ) {32 this.buffer = circularBuffer;31 public RawLogMessage( final RingBuffer ringBuffer ) { 32 this.buffer = ringBuffer; 33 33 } 34 34 -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/formatters/SimpleLogMessage.java
r590 r594 1 1 package com.db.logger.api.impl.logger.formatters; 2 2 3 import com.db.logger.api.FluentLogBuilder;4 3 import com.db.logger.api.LogMessage; 5 import com.db.logger.api.impl.logger. CircularBuffer;4 import com.db.logger.api.impl.logger.RingBuffer; 6 5 import net.jcip.annotations.NotThreadSafe; 7 6 … … 24 23 final int formatId, 25 24 final int argumentsCount, 26 final CircularBuffer circularBuffer ) {27 super( circularBuffer );25 final RingBuffer ringBuffer ) { 26 super( ringBuffer ); 28 27 this.format = format; 29 28 -
Tests/JAVA/logger/src/main/java/com/db/logger/api/impl/logger/formatters/SimpleLogMessageExpanded.java
r590 r594 3 3 import com.db.logger.api.FluentLogBuilder; 4 4 import com.db.logger.api.LogMessage; 5 import com.db.logger.api.impl.logger. CircularBuffer;5 import com.db.logger.api.impl.logger.RingBuffer; 6 6 import com.db.logger.api.impl.logger.RecordHelper; 7 7 8 import static com.db.logger.api.impl.logger. DemultiplexingSequencer.INVALID_INDEX;8 import static com.db.logger.api.impl.logger.MCSDSequencer.INVALID_INDEX; 9 9 import static com.db.logger.api.impl.logger.RecordHelper.RecordType.LOG_RECORD; 10 10 import static com.db.logger.api.impl.logger.formatters.AbstractLogBuilder.NOT_SET; … … 17 17 public final class SimpleLogMessageExpanded implements LogMessage, FluentLogBuilder { 18 18 19 private final CircularBuffer buffer;19 private final RingBuffer buffer; 20 20 21 21 private int argumentIndex = NOT_SET; … … 30 30 final int formatId, 31 31 final int argumentsCount, 32 final CircularBuffer circularBuffer ) {33 this.buffer = circularBuffer;32 final RingBuffer ringBuffer ) { 33 this.buffer = ringBuffer; 34 34 this.format = format; 35 35 -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/BufferWriteAndDrainBenchmark.java
r593 r594 4 4 import java.util.concurrent.atomic.AtomicInteger; 5 5 6 import com.db.logger.api.impl.logger.DemultiplexingSequencer; 7 import com.db.logger.api.impl.logger.RecordHelper; 6 import com.db.logger.api.impl.logger.*; 8 7 import com.db.logger.api.impl.logger.buffer.DirectAccessLongBuffer; 9 8 import com.db.logger.api.impl.logger.buffer.ILongsBuffer; 10 import com.db.logger.api.impl.logger.WaitingStrategy;11 9 import org.openjdk.jmh.annotations.*; 12 10 import org.openjdk.jmh.logic.BlackHole; 13 11 14 12 import static com.db.logger.api.impl.logger.RecordHelper.NOT_SET; 13 import static com.db.logger.api.impl.logger.RecordHelper.RecordType.LOG_RECORD; 14 import static com.db.logger.api.impl.logger.RecordHelper.header; 15 15 16 16 /** … … 30 30 public static final AtomicInteger ID_GENERATOR = new AtomicInteger( 1 ); 31 31 32 public static final DemultiplexingSequencer.Drainer DRAIN_DUMMY = new DemultiplexingSequencer.Drainer() {32 public static final Sequencer.Drainer DRAIN_DUMMY = new Sequencer.Drainer() { 33 33 @Override 34 34 public int available( final long startSequence, … … 43 43 44 44 public ILongsBuffer buffer; 45 public DemultiplexingSequencer sequencer;45 public MCSDSequencer sequencer; 46 46 47 public DemultiplexingSequencer.Drainer DRAIN_AND_READ;47 public Sequencer.Drainer DRAIN_AND_READ; 48 48 49 49 @Setup 50 50 public void setup() { 51 51 final int length = 1 << LENGTH_POW; 52 buffer = new DirectAccessLongBuffer( length, RecordHelper.NOT_SET );53 sequencer = new DemultiplexingSequencer( length );52 buffer = new DirectAccessLongBuffer( length, NOT_SET ); 53 sequencer = new MCSDSequencer( length ); 54 54 55 DRAIN_AND_READ = new DemultiplexingSequencer.Drainer() { 56 @Override 57 public int available( final long startSequence, 58 final long sentinelSequence ) { 59 int spinsAvailable = 256; 60 for( long pos = startSequence; pos < sentinelSequence; pos++ ) { 61 if( ( pos % CELLS_PER_RECORD ) == 0 ) { 62 for(; spinsAvailable >= 0; spinsAvailable-- ) { 63 final long header = buffer.getVolatile( pos ); 64 if( header > 0 ) { 65 buffer.put( pos, NOT_SET ); 66 break; 67 } 68 } 69 if( spinsAvailable < 0 ) { 70 return ( int ) ( pos - startSequence ); 71 } 72 } else { 73 buffer.get( pos ); 74 } 75 } 76 return ( int ) ( sentinelSequence - startSequence ); 77 } 78 }; 55 DRAIN_AND_READ = new ConsumingDrainer( buffer ); 79 56 } 80 57 … … 157 134 } 158 135 //write header with SA 159 buffer.putOrdered( position, writerId ); 136 final long header = header( LOG_RECORD, writerId, cellsCount - 1 ); 137 buffer.putOrdered( position, header ); 160 138 } 161 139 -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/ConsumingDrainer.java
r590 r594 1 1 package com.db.logger.benchmarks; 2 2 3 import com.db.logger.api.impl.logger. DemultiplexingSequencer;3 import com.db.logger.api.impl.logger.MCSDSequencer; 4 4 import com.db.logger.api.impl.logger.RecordHelper; 5 5 import com.db.logger.api.impl.logger.buffer.ILongsBuffer; … … 12 12 * created 06.12.13 at 2:07 13 13 */ 14 public class ConsumingDrainer implements DemultiplexingSequencer.Drainer {14 public class ConsumingDrainer implements MCSDSequencer.Drainer { 15 15 private static final int SPINS_PER_TURN = 256; 16 16 -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/FastLoggerWithoutWriteBenchmark.java
r590 r594 30 30 private static final Logger log = Logger.getLogger( FastLoggerWithoutWriteBenchmark.class ); 31 31 public static final int LENGTH = Integer.getInteger( "length", 1 << 14 ); 32 /** 33 * It's CELLS-1 arguments + 1 cell for header -- to be consistent with previous 34 * benchmarks 35 */ 32 36 public static final int CELLS_PER_RECORD = Integer.getInteger( "cells-per-record", 8 );//8longs = 1 cache line 33 37 public static final int WRITER_BACKOFF = Integer.getInteger( "writer-backoff", 20 ); … … 43 47 44 48 public ILongsBuffer buffer; 45 public DemultiplexingSequencer sequencer;49 public MCSDSequencer sequencer; 46 50 47 51 public FastLoggerImpl logger; … … 50 54 public void setup() { 51 55 buffer = new DirectAccessLongBuffer( LENGTH, RecordHelper.NOT_SET ); 52 sequencer = new DemultiplexingSequencer( LENGTH );56 sequencer = new MCSDSequencer( LENGTH ); 53 57 logger = new FastLoggerImpl( 54 58 new ThreadFactory() { … … 97 101 } 98 102 FluentLogBuilder logBuilder = ts.simpleMessage.with( 5d ); 99 final int count = CELLS_PER_RECORD ;103 final int count = CELLS_PER_RECORD - 1; 100 104 for( int i = 1; i < count; i++ ) { 101 105 logBuilder = logBuilder.with( ( long ) i ); … … 115 119 } 116 120 FluentLogBuilder logBuilder = ts.threadLocalMessage.with( 5d ); 117 final int count = CELLS_PER_RECORD ;121 final int count = CELLS_PER_RECORD - 1; 118 122 for( int i = 1; i < count; i++ ) { 119 123 logBuilder = logBuilder.with( ( long ) i ); … … 128 132 @Group( "logAndPayload" ) 129 133 @GroupThreads( 3 ) 130 public void write Message( final ThreadState ts ) {134 public void writeRawMessage( final ThreadState ts ) { 131 135 FluentLogBuilder logBuilder = logger.message( ts.messageFormat ) 132 136 .with( 5d ); 133 final int count = CELLS_PER_RECORD ;134 for( int i = 1; i < count; i++ ) { 135 logBuilder = logBuilder.with( ( long ) i ); 136 } 137 logBuilder.log(); 138 139 BlackHole.consumeCPU( WRITER_BACKOFF ); 140 } 141 142 //@GenerateMicroBenchmark143 //@Group( "lookupMessageInfo" )144 //@GroupThreads( 3 )145 //public Object lookupMessageInfo( final ThreadState ts ) {146 //return logger.lookupMessageInfo( ts.messageFormat );147 //}137 final int count = CELLS_PER_RECORD - 1; 138 for( int i = 1; i < count; i++ ) { 139 logBuilder = logBuilder.with( ( long ) i ); 140 } 141 logBuilder.log(); 142 143 BlackHole.consumeCPU( WRITER_BACKOFF ); 144 } 145 146 @GenerateMicroBenchmark 147 @Group( "lookupMessageInfo" ) 148 @GroupThreads( 3 ) 149 public Object lookupMessageInfo( final ThreadState ts ) { 150 return logger.lookupMessageInfo( ts.messageFormat ); 151 } 148 152 149 153 @State( Scope.Thread ) … … 156 160 final StringBuilder sb = new StringBuilder(); 157 161 sb.append( id ); 158 for( int i = 0; i < CELLS_PER_RECORD; i++ ) { 162 //actually, it's CELLS-1 arguments + 1 cell for header -- to be consistent 163 //with previous benchmarks 164 for( int i = 1; i < CELLS_PER_RECORD; i++ ) { 159 165 sb.append( " %d" ); 160 166 } -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/MultiBuffersWriteAndDrainBenchmark.java
r593 r594 1 1 package com.db.logger.benchmarks; 2 2 3 import java.util.*; 4 import java.util.concurrent.CopyOnWriteArrayList; 3 5 import java.util.concurrent.TimeUnit; 4 6 import java.util.concurrent.atomic.AtomicInteger; 5 7 6 import com.db.logger.api.impl.logger.DemultiplexingSequencer; 7 import com.db.logger.api.impl.logger.RecordHelper; 8 import com.db.logger.api.impl.logger.*; 8 9 import com.db.logger.api.impl.logger.buffer.DirectAccessLongBuffer; 9 10 import com.db.logger.api.impl.logger.buffer.ILongsBuffer; 10 import com.db.logger.api.impl.logger.WaitingStrategy;11 11 import org.openjdk.jmh.annotations.*; 12 12 import org.openjdk.jmh.logic.BlackHole; 13 13 14 import static com.db.logger.api.impl.logger.RecordHelper.NOT_SET; 14 import static com.db.logger.api.impl.logger.RecordHelper.RecordType.LOG_RECORD; 15 import static com.db.logger.api.impl.logger.RecordHelper.header; 15 16 16 17 /** 18 * We use many (3) single-writer single-reader ring buffers, one per each 19 * 'logging' thread, instead of one multi-writer single reader ring buffer 20 * for all them at once. 21 * 17 22 * @author ruslan 18 23 * created 22.11.13 at 20:04 … … 21 26 @OutputTimeUnit( TimeUnit.NANOSECONDS ) 22 27 @State( Scope.Group ) 23 public class BufferWriteAndDrainBenchmark {28 public class MultiBuffersWriteAndDrainBenchmark { 24 29 public static final int LENGTH_POW = Integer.getInteger( "length-pow", 14 ); 25 30 public static final int CELLS_PER_RECORD = Integer.getInteger( "cells-per-record", 8 );//8longs = 1 cache line … … 30 35 public static final AtomicInteger ID_GENERATOR = new AtomicInteger( 1 ); 31 36 32 public static final DemultiplexingSequencer.Drainer DRAIN_DUMMY = new DemultiplexingSequencer.Drainer() {37 public static final Sequencer.Drainer DRAIN_DUMMY = new MCSDSequencer.Drainer() { 33 38 @Override 34 39 public int available( final long startSequence, … … 42 47 } 43 48 44 public ILongsBuffer buffer;45 public DemultiplexingSequencer sequencer;46 47 public DemultiplexingSequencer.Drainer DRAIN_AND_READ;48 49 49 50 @Setup 50 51 public void setup() { 51 final int length = 1 << LENGTH_POW;52 buffer = new DirectAccessLongBuffer( length, RecordHelper.NOT_SET );53 sequencer = new DemultiplexingSequencer( length );54 55 DRAIN_AND_READ = new DemultiplexingSequencer.Drainer() {56 @Override57 public int available( final long startSequence,58 final long sentinelSequence ) {59 int spinsAvailable = 256;60 for( long pos = startSequence; pos < sentinelSequence; pos++ ) {61 if( ( pos % CELLS_PER_RECORD ) == 0 ) {62 for(; spinsAvailable >= 0; spinsAvailable-- ) {63 final long header = buffer.getVolatile( pos );64 if( header > 0 ) {65 buffer.put( pos, NOT_SET );66 break;67 }68 }69 if( spinsAvailable < 0 ) {70 return ( int ) ( pos - startSequence );71 }72 } else {73 buffer.get( pos );74 }75 }76 return ( int ) ( sentinelSequence - startSequence );77 }78 };79 52 } 80 53 81 54 @TearDown 82 55 public void tearDown() { 83 56 states.clear(); 84 57 } 85 58 … … 88 61 //TODO set thread affinity 89 62 } 63 64 public static final List<ThreadState> states = new CopyOnWriteArrayList<ThreadState>(); 90 65 91 66 /*=============================================================================*/ … … 102 77 @GroupThreads( 3 )//actually it's (CORES-1) 103 78 public void writer( final ThreadState ts ) { 104 writeEntry( ts .id, ts.count );79 writeEntry( ts, ts.id, ts.count ); 105 80 BlackHole.consumeCPU( WRITER_BACKOFF ); 106 81 } … … 112 87 //mostly we do not care about drain latency here, measure just to be aware of it 113 88 try { 114 sequencer.drainTo( DRAIN_DUMMY ); 89 for( final ThreadState ts : states ) { 90 ts.ringBuffer.drainTo( DRAIN_DUMMY ); 91 } 115 92 BlackHole.consumeCPU( 10 ); 116 93 } catch( Throwable e ) { … … 126 103 @GroupThreads( 3 ) //actually it's (CORES-1) 127 104 public void writer2( final ThreadState ts ) { 128 writeEntry( ts .id, ts.count );105 writeEntry( ts, ts.id, ts.count ); 129 106 BlackHole.consumeCPU( WRITER_BACKOFF ); 130 107 } … … 136 113 //mostly we do not care about drain latency here, measure just to be aware of it 137 114 try { 138 sequencer.drainTo( DRAIN_AND_READ ); 115 for( final ThreadState ts : states ) { 116 ts.ringBuffer.drainTo( ts.consumingDrainer ); 117 } 139 118 // BlackHole.consumeCPU( 100 ); 140 119 } catch( Throwable e ) { … … 145 124 /*=============================================================================*/ 146 125 147 private void writeEntry( final int writerId, 126 private void writeEntry( final ThreadState ts, 127 final int writerId, 148 128 final int cellsCount ) { 149 final long position = sequencer.claim( cellsCount, WAITING_STRATEGY);129 final long position = ts.ringBuffer.claim( cellsCount ); 150 130 if( position < 0 ) { 151 131 System.err.println( "Timeout" ); … … 153 133 } 154 134 //reserve 0-th cell for header 135 final ILongsBuffer data = ts.ringBuffer.buffer(); 155 136 for( int i = 1; i < cellsCount; i++ ) { 156 buffer.put( position + i, i );137 data.put( position + i, i ); 157 138 } 158 139 //write header with SA 159 buffer.putOrdered( position, writerId ); 140 data.putOrdered( 141 position, 142 header( 143 LOG_RECORD, 144 writerId, 145 cellsCount - 1 146 ) 147 ); 160 148 } 161 149 … … 164 152 public final int id = ID_GENERATOR.incrementAndGet(); 165 153 public final int count = CELLS_PER_RECORD;//but 1 for header 154 155 public RingBuffer ringBuffer; 156 public Sequencer.Drainer consumingDrainer; 157 158 public ThreadState() { 159 final int length = 1 << LENGTH_POW; 160 final DirectAccessLongBuffer longBuffer = new DirectAccessLongBuffer( 161 length, 162 RecordHelper.NOT_SET 163 ); 164 165 ringBuffer = new RingBuffer( 166 new SCSDSequencer( length ), 167 longBuffer, 168 WAITING_STRATEGY 169 ); 170 171 consumingDrainer = new ConsumingDrainer( longBuffer ); 172 } 173 174 @Setup 175 public void setup() { 176 states.add( this ); 177 } 178 179 @TearDown 180 public void destroy() { 181 states.remove( this ); 182 } 166 183 } 167 184 168 185 public static void main( final String[] args ) throws Exception { 169 final BufferWriteAndDrainBenchmark benchmark = new BufferWriteAndDrainBenchmark();186 final MultiBuffersWriteAndDrainBenchmark benchmark = new MultiBuffersWriteAndDrainBenchmark(); 170 187 171 188 benchmark.setup(); … … 196 213 Thread.sleep( 300000 ); 197 214 } 215 198 216 } -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/RawLogMessageWriteAndDrainBenchmark.java
r590 r594 35 35 36 36 public ILongsBuffer buffer; 37 public DemultiplexingSequencer sequencer;37 public MCSDSequencer sequencer; 38 38 39 public DemultiplexingSequencer.Drainer readingConsumer;39 public MCSDSequencer.Drainer readingConsumer; 40 40 41 41 @Setup 42 42 public void setup() { 43 43 buffer = new DirectAccessLongBuffer( LENGTH, RecordHelper.NOT_SET ); 44 sequencer = new DemultiplexingSequencer( LENGTH );44 sequencer = new MCSDSequencer( LENGTH ); 45 45 46 46 readingConsumer = new ConsumingDrainer( buffer ); … … 103 103 public void setup( final RawLogMessageWriteAndDrainBenchmark b ) { 104 104 formatter = new RawLogMessage( 105 new CircularBuffer( b.sequencer, b.buffer, WAITING_STRATEGY )105 new RingBuffer( b.sequencer, b.buffer, WAITING_STRATEGY ) 106 106 ).setup( 107 107 new MessageInfo( -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/SimpleLogMessageWriteAndDrainBenchmark.java
r590 r594 8 8 import com.db.logger.api.impl.logger.buffer.DirectAccessLongBuffer; 9 9 import com.db.logger.api.impl.logger.buffer.ILongsBuffer; 10 import com.db.logger.api.impl.logger.formatters.SimpleLogMessage;11 10 import com.db.logger.api.impl.logger.formatters.SimpleLogMessageExpanded; 12 11 import org.openjdk.jmh.annotations.*; 13 12 import org.openjdk.jmh.logic.BlackHole; 14 15 import static com.db.logger.api.impl.logger.RecordHelper.*;16 13 17 14 /** … … 36 33 37 34 public ILongsBuffer buffer; 38 public DemultiplexingSequencer sequencer;35 public MCSDSequencer sequencer; 39 36 40 public DemultiplexingSequencer.Drainer readingConsumer;37 public MCSDSequencer.Drainer readingConsumer; 41 38 42 39 @Setup 43 40 public void setup() { 44 41 buffer = new DirectAccessLongBuffer( LENGTH, RecordHelper.NOT_SET ); 45 sequencer = new DemultiplexingSequencer( LENGTH );42 sequencer = new MCSDSequencer( LENGTH ); 46 43 47 44 readingConsumer = new ConsumingDrainer( buffer ); … … 106 103 id, 107 104 CELLS_PER_RECORD - 1, 108 new CircularBuffer( b.sequencer, b.buffer, WAITING_STRATEGY )105 new RingBuffer( b.sequencer, b.buffer, WAITING_STRATEGY ) 109 106 ); 110 107 } -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/helpers/MCSDSequencerBenchmark.java
r593 r594 4 4 import java.util.concurrent.atomic.AtomicInteger; 5 5 6 import com.db.logger.api.impl.logger. DemultiplexingSequencer;6 import com.db.logger.api.impl.logger.MCSDSequencer; 7 7 import com.db.logger.api.impl.logger.WaitingStrategy; 8 8 import org.apache.log4j.BasicConfigurator; … … 14 14 * Here we measure raw sequencer performance: just position claiming/reclaiming 15 15 * <p/> 16 * TODO: sometimes hangs! why?17 16 * 18 17 * @author ruslan … … 22 21 @OutputTimeUnit( TimeUnit.NANOSECONDS ) 23 22 @State( Scope.Group ) 24 public class SequencerBenchmark {25 private static final Logger log = Logger.getLogger( SequencerBenchmark.class );23 public class MCSDSequencerBenchmark { 24 private static final Logger log = Logger.getLogger( MCSDSequencerBenchmark.class ); 26 25 27 26 public static final int LENGTH = Integer.getInteger( "length", 1 << 14 ); … … 38 37 public static final AtomicInteger ID_GENERATOR = new AtomicInteger( 1 ); 39 38 40 public static final DemultiplexingSequencer.Drainer DRAIN_DUMMY = new DemultiplexingSequencer.Drainer() {39 public static final MCSDSequencer.Drainer DRAIN_DUMMY = new MCSDSequencer.Drainer() { 41 40 @Override 42 41 public int available( final long startSequence, … … 47 46 48 47 49 public DemultiplexingSequencer sequencer;48 public MCSDSequencer sequencer; 50 49 51 50 @Setup 52 51 public void setup() { 53 sequencer = new DemultiplexingSequencer( LENGTH );52 sequencer = new MCSDSequencer( LENGTH ); 54 53 } 55 54 … … 103 102 104 103 public static void main( final String[] args ) throws Exception { 105 final SequencerBenchmark benchmark = newSequencerBenchmark();104 final MCSDSequencerBenchmark benchmark = new MCSDSequencerBenchmark(); 106 105 107 106 benchmark.setup(); -
Tests/JAVA/logger/src/main/java/com/db/logger/benchmarks/helpers/SCSDSequencerBenchmark.java
r593 r594 1 1 package com.db.logger.benchmarks.helpers; 2 2 3 import java.util.*; 4 import java.util.concurrent.CopyOnWriteArrayList; 3 5 import java.util.concurrent.TimeUnit; 4 6 import java.util.concurrent.atomic.AtomicInteger; 5 7 6 import com.db.logger.api.impl.logger.DemultiplexingSequencer; 8 import com.db.logger.api.impl.logger.MCSDSequencer; 9 import com.db.logger.api.impl.logger.SCSDSequencer; 7 10 import com.db.logger.api.impl.logger.WaitingStrategy; 8 11 import org.apache.log4j.BasicConfigurator; … … 13 16 /** 14 17 * Here we measure raw sequencer performance: just position claiming/reclaiming 18 * It is single-claimer single-drainer (SCSD) sequencer 15 19 * <p/> 16 * TODO: sometimes hangs! why?17 20 * 18 21 * @author ruslan … … 22 25 @OutputTimeUnit( TimeUnit.NANOSECONDS ) 23 26 @State( Scope.Group ) 24 public class S equencerBenchmark {25 private static final Logger log = Logger.getLogger( S equencerBenchmark.class );27 public class SCSDSequencerBenchmark { 28 private static final Logger log = Logger.getLogger( SCSDSequencerBenchmark.class ); 26 29 27 30 public static final int LENGTH = Integer.getInteger( "length", 1 << 14 ); … … 38 41 public static final AtomicInteger ID_GENERATOR = new AtomicInteger( 1 ); 39 42 40 public static final DemultiplexingSequencer.Drainer DRAIN_DUMMY = new DemultiplexingSequencer.Drainer() {43 public static final MCSDSequencer.Drainer DRAIN_DUMMY = new MCSDSequencer.Drainer() { 41 44 @Override 42 45 public int available( final long startSequence, … … 47 50 48 51 49 public DemultiplexingSequencer sequencer;52 public static final List<ThreadState> sequencers = new CopyOnWriteArrayList<ThreadState>(); 50 53 51 54 @Setup 52 55 public void setup() { 53 sequencer = new DemultiplexingSequencer( LENGTH ); 56 54 57 } 55 58 56 59 @TearDown 57 60 public void tearDown() { 58 61 sequencers.clear(); 59 62 } 60 63 … … 77 80 @GroupThreads( 3 )//actually it's (CORES-1) 78 81 public void claimer3( final ThreadState ts ) { 79 claimEntry( ts. id, ts.count );82 claimEntry( ts.sequencer, ts.id, ts.count ); 80 83 BlackHole.consumeCPU( WRITER_BACKOFF ); 81 84 } … … 85 88 @GroupThreads( 1 ) 86 89 public void drainer() { 87 sequencer.drainTo( DRAIN_DUMMY ); 88 BlackHole.consumeCPU( WRITER_BACKOFF ); 90 for( final ThreadState ts : sequencers ) { 91 ts.sequencer.drainTo( DRAIN_DUMMY ); 92 } 93 // BlackHole.consumeCPU( WRITER_BACKOFF ); 89 94 } 90 95 91 96 /*=============================================================================*/ 92 97 93 private long claimEntry( final int writerId, 98 private long claimEntry( final SCSDSequencer sequencer, 99 final int writerId, 94 100 final int cellsCount ) { 95 101 return sequencer.claim( cellsCount, WAITING_STRATEGY ); … … 100 106 public final int id = ID_GENERATOR.incrementAndGet(); 101 107 public final int count = CELLS_PER_RECORD; 108 109 public SCSDSequencer sequencer; 110 111 @Setup 112 public void setup() { 113 sequencer = new SCSDSequencer( LENGTH ); 114 sequencers.add( this ); 115 } 116 117 @TearDown 118 public void destroy() { 119 sequencers.remove( this ); 120 } 102 121 } 103 122 104 123 public static void main( final String[] args ) throws Exception { 105 final S equencerBenchmark benchmark = newSequencerBenchmark();124 final SCSDSequencerBenchmark benchmark = new SCSDSequencerBenchmark(); 106 125 107 126 benchmark.setup(); -
Tests/JAVA/logger/src/test/java/com/db/logger/api/impl/logger/MCSDSequencerTest.java
r589 r594 1 1 package com.db.logger.api.impl.logger; 2 3 import org.junit.Test;4 5 import static com.db.logger.api.impl.logger.DemultiplexingSequencer.INVALID_INDEX;6 import static org.junit.Assert.*;7 2 8 3 /** … … 10 5 * created 7/4/12 at 4:25 PM 11 6 */ 12 public class DemultiplexingSequencerTest { 13 14 15 @Test( expected = IllegalArgumentException.class ) 16 public void cantCreateEmptySequencer() throws Exception { 17 new DemultiplexingSequencer( 0 ); 18 } 19 20 @Test 21 public void sequencerSizeIndexesAvailableInFreshSequencer() throws Exception { 22 final int size = 4; 23 final DemultiplexingSequencer sequencer = createSequencer( size ); 24 for( int i = 0; i < size; i++ ) { 25 assertNotEquals( INVALID_INDEX, sequencer.claim() ); 26 } 27 } 28 29 @Test 30 public void nextAvailableReturnsInvalidIndexWhenSequencerExhausted() throws Exception { 31 final int size = 4; 32 final DemultiplexingSequencer sequencer = createSequencer( size ); 33 34 assertExactIndexesAvailable( sequencer, size ); 35 } 36 37 @Test 38 public void drainerNotCalledIfNothingClaimedYet() throws Exception { 39 final int size = 4; 40 final DemultiplexingSequencer sequencer = createSequencer( size ); 41 sequencer.drainTo( new DemultiplexingSequencer.Drainer() { 42 @Override 43 public int available( final long startSequence, 44 final long sentinelSequence ) { 45 fail( "Called with " + startSequence + ", " + sentinelSequence ); 46 return 0; 47 } 48 } ); 49 } 50 51 @Test 52 public void drainToSuppliesEveryIndexInClaimedRange() throws Exception { 53 final int size = 4; 54 final DemultiplexingSequencer sequencer = createSequencer( size ); 55 exhaustSequencer( sequencer, size ); 56 sequencer.drainTo( new DemultiplexingSequencer.Drainer() { 57 @Override 58 public int available( final long startSequence, 59 final long sentinelSequence ) { 60 assertEquals( 0, startSequence ); 61 assertEquals( size, sentinelSequence ); 62 return 0; 63 } 64 } ); 65 66 } 67 68 @Test 69 public void drainMakesEntriesAvailableForReuse() throws Exception { 70 final int size = 4; 71 72 final DemultiplexingSequencer sequencer = createSequencer( size ); 73 74 exhaustSequencer( sequencer, size ); 75 76 sequencer.drainTo( new DemultiplexingSequencer.Drainer() { 77 @Override 78 public int available( final long startSequence, 79 final long sentinelSequence ) { 80 return ( int ) ( sentinelSequence - startSequence ); 81 } 82 } ); 83 84 assertExactIndexesAvailable( sequencer, size ); 85 } 86 87 @Test( expected = IllegalStateException.class ) 88 public void drainFailsIfReturnedNegativeValue() throws Exception { 89 final int size = 4; 90 91 final DemultiplexingSequencer sequencer = createSequencer( size ); 92 93 exhaustSequencer( sequencer, size ); 94 95 sequencer.drainTo( new DemultiplexingSequencer.Drainer() { 96 @Override 97 public int available( final long startSequence, 98 final long sentinelSequence ) { 99 return -1; 100 } 101 } ); 102 } 103 104 @Test( expected = IllegalStateException.class ) 105 public void drainFailsIfReturnedLengthMoreThenMaximum() throws Exception { 106 final int size = 4; 107 108 final DemultiplexingSequencer sequencer = createSequencer( size ); 109 110 exhaustSequencer( sequencer, size ); 111 112 sequencer.drainTo( new DemultiplexingSequencer.Drainer() { 113 @Override 114 public int available( final long startSequence, 115 final long sentinelSequence ) { 116 final long length = sentinelSequence - startSequence; 117 return ( int ) ( length + 1 ); 118 } 119 } ); 120 } 121 122 123 @Test 124 public void drainToMakesAvailableToReuseOnlyDrainedIndexes() throws Exception { 125 final int size = 4; 126 127 final DemultiplexingSequencer sequencer = createSequencer( size ); 128 129 exhaustSequencer( sequencer, size ); 130 131 final int toProcess = 2; 132 133 sequencer.drainTo( new DemultiplexingSequencer.Drainer() { 134 @Override 135 public int available( final long startSequence, 136 final long sentinelSequence ) { 137 return toProcess; 138 } 139 } ); 140 141 assertExactIndexesAvailable( sequencer, toProcess ); 142 } 143 144 @Test 145 public void exceptionInProcessorJustStopsProcessingAndChangeNothing() throws Exception { 146 final int size = 4; 147 148 final DemultiplexingSequencer sequencer = createSequencer( size ); 149 150 exhaustSequencer( sequencer, size ); 151 152 try { 153 sequencer.drainTo( new DemultiplexingSequencer.Drainer() { 154 @Override 155 public int available( final long startSequence, 156 final long sentinelSequence ) { 157 throw new RuntimeException(); 158 } 159 } ); 160 fail( "Exception was suppressed!" ); 161 } catch( RuntimeException e ) { 162 } 163 164 assertExactIndexesAvailable( sequencer, 0 ); 165 } 166 167 private void exhaustSequencer( final DemultiplexingSequencer sequencer, 168 final int size ) { 169 for( int i = 0; i < size; i++ ) { 170 sequencer.claim(); 171 } 172 } 173 174 private static DemultiplexingSequencer createSequencer( final int size ) { 175 return new DemultiplexingSequencer( size ); 176 } 177 178 179 private static void assertExactIndexesAvailable( final DemultiplexingSequencer sequencer, 180 final int expectedAvailable ) { 181 for( int i = 0; i < expectedAvailable; i++ ) { 182 assertNotEquals( i + " from " + expectedAvailable + " expected", 183 INVALID_INDEX, 184 sequencer.claim() 185 ); 186 } 187 assertEquals( 188 "More entries, then expected(" + expectedAvailable + ")", 189 INVALID_INDEX, 190 sequencer.claim() 191 ); 7 public class MCSDSequencerTest extends SequencerTestBase { 8 @Override 9 protected Sequencer createSequencer( final int size ) { 10 return new MCSDSequencer( size ); 192 11 } 193 12 }
Note: See TracChangeset
for help on using the changeset viewer.