[JAVA-22519] Move articles from generic libraries module to specific library modules (#15416)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
package com.baeldung.jctools;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jctools.queues.MpmcArrayQueue;
|
||||
import org.jctools.queues.atomic.MpmcAtomicArrayQueue;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Group;
|
||||
import org.openjdk.jmh.annotations.GroupThreads;
|
||||
import org.openjdk.jmh.annotations.Level;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.infra.Control;
|
||||
|
||||
@BenchmarkMode(Mode.SampleTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@Fork(1)
|
||||
@Warmup(iterations = 1)
|
||||
@Measurement(iterations = 3)
|
||||
@State(Scope.Group)
|
||||
public class MpmcBenchmark {
|
||||
|
||||
public static final String PARAM_UNSAFE = "MpmcArrayQueue";
|
||||
public static final String PARAM_AFU = "MpmcAtomicArrayQueue";
|
||||
public static final String PARAM_JDK = "ArrayBlockingQueue";
|
||||
|
||||
public static final int PRODUCER_THREADS_NUMBER = 32;
|
||||
public static final int CONSUMER_THREADS_NUMBER = 32;
|
||||
|
||||
public static final String GROUP_NAME = "MyGroup";
|
||||
|
||||
public static final int CAPACITY = 128;
|
||||
|
||||
@Param({PARAM_UNSAFE, PARAM_AFU, PARAM_JDK})
|
||||
public volatile String implementation;
|
||||
|
||||
public volatile Queue<Long> queue;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
switch (implementation) {
|
||||
case PARAM_UNSAFE:
|
||||
queue = new MpmcArrayQueue<>(CAPACITY);
|
||||
break;
|
||||
case PARAM_AFU:
|
||||
queue = new MpmcAtomicArrayQueue<>(CAPACITY);
|
||||
break;
|
||||
case PARAM_JDK:
|
||||
queue = new ArrayBlockingQueue<>(CAPACITY);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported implementation " + implementation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
@Group(GROUP_NAME)
|
||||
@GroupThreads(PRODUCER_THREADS_NUMBER)
|
||||
public void write(Control control) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (!control.stopMeasurement && !queue.offer(1L)) {
|
||||
// Is intentionally left blank
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(GROUP_NAME)
|
||||
@GroupThreads(CONSUMER_THREADS_NUMBER)
|
||||
public void read(Control control) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while (!control.stopMeasurement && queue.poll() == null) {
|
||||
// Is intentionally left blank
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
## How to build and run the JMH benchmark
|
||||
|
||||
Execute the following from the project's root:
|
||||
```bash
|
||||
mvn clean install
|
||||
java -jar ./target/benchmarks.jar MpmcBenchmark -si true
|
||||
```
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.baeldung.jctools;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.jctools.queues.SpscArrayQueue;
|
||||
import org.jctools.queues.SpscChunkedArrayQueue;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JCToolsUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenMultipleProducers_whenSpscQueueUsed_thenNoWarningOccurs() throws InterruptedException {
|
||||
SpscArrayQueue<Integer> queue = new SpscArrayQueue<Integer>(2);
|
||||
|
||||
Thread producer1 = new Thread(() -> {
|
||||
queue.offer(1);
|
||||
});
|
||||
producer1.start();
|
||||
producer1.join();
|
||||
|
||||
Thread producer2 = new Thread(() -> {
|
||||
queue.offer(2);
|
||||
});
|
||||
producer2.start();
|
||||
producer2.join();
|
||||
|
||||
Set<Integer> fromQueue = new HashSet<>();
|
||||
Thread consumer = new Thread(() -> queue.drain(fromQueue::add));
|
||||
consumer.start();
|
||||
consumer.join();
|
||||
|
||||
assertThat(fromQueue).containsOnly(1, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenQueueIsFull_thenNoMoreElementsCanBeAdded() throws InterruptedException {
|
||||
SpscChunkedArrayQueue<Integer> queue = new SpscChunkedArrayQueue<>(8, 16);
|
||||
Assertions.assertThat(queue.capacity()).isEqualTo(16);
|
||||
|
||||
CountDownLatch startConsuming = new CountDownLatch(1);
|
||||
CountDownLatch awakeProducer = new CountDownLatch(1);
|
||||
AtomicReference<Throwable> error = new AtomicReference<>();
|
||||
Thread producer = new Thread(() -> {
|
||||
IntStream.range(0, queue.capacity()).forEach(i -> {
|
||||
Assertions.assertThat(queue.offer(i)).isTrue();
|
||||
});
|
||||
Assertions.assertThat(queue.offer(queue.capacity())).isFalse();
|
||||
startConsuming.countDown();
|
||||
try {
|
||||
awakeProducer.await();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Assertions.assertThat(queue.offer(queue.capacity())).isTrue();
|
||||
});
|
||||
producer.setUncaughtExceptionHandler((t, e) -> {
|
||||
error.set(e);
|
||||
startConsuming.countDown();
|
||||
});
|
||||
producer.start();
|
||||
|
||||
startConsuming.await();
|
||||
|
||||
if (error.get() != null) {
|
||||
fail("Producer's assertion failed", error.get());
|
||||
}
|
||||
|
||||
Set<Integer> fromQueue = new HashSet<>();
|
||||
queue.drain(fromQueue::add);
|
||||
awakeProducer.countDown();
|
||||
producer.join();
|
||||
queue.drain(fromQueue::add);
|
||||
|
||||
assertThat(fromQueue).containsAll(IntStream.range(0, 17).boxed().collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user