/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.collection;
import fj.P;
import io.vavr.JmhRunner;
import io.vavr.Tuple2;
import org.junit.Test;
import org.openjdk.jmh.annotations.*;
import scala.math.Ordering;
import scala.math.Ordering$;
import scalaz.Heap;
import scalaz.Order;
import scalaz.Order$;
import java.util.Collections;
import static java.util.Arrays.asList;
import static io.vavr.JmhRunner.create;
import static io.vavr.JmhRunner.getRandomValues;
import static scala.collection.JavaConverters.asScalaBuffer;
@SuppressWarnings({ "UnnecessaryFullyQualifiedName", "UnnecessarilyQualifiedInnerClassAccess" })
public class PriorityQueueBenchmark {
static final Array<Class<?>> CLASSES = Array.of(
Enqueue.class,
Dequeue.class,
Sort.class
);
@Test
public void testAsserts() {
JmhRunner.runDebugWithAsserts(CLASSES);
}
public static void main(String... args) {
JmhRunner.runDebugWithAsserts(CLASSES);
JmhRunner.runNormalNoAsserts(CLASSES);
}
@State(Scope.Benchmark)
public static class Base {
static final Ordering<Integer> SCALA_ORDERING = Ordering$.MODULE$.comparatorToOrdering(Integer::compareTo);
static final Order<Integer> SCALAZ_ORDER = Order$.MODULE$.fromScalaOrdering(SCALA_ORDERING);
@Param({ "10", "100", "1000" })
public int CONTAINER_SIZE;
int EXPECTED_AGGREGATE;
Integer[] ELEMENTS;
scalaz.Heap<Integer> scalazPersistent;
io.vavr.collection.PriorityQueue<Integer> vavrPersistent;
fj.data.PriorityQueue<Integer, Integer> fjava_persistent;
@Setup
public void setup() {
ELEMENTS = getRandomValues(CONTAINER_SIZE, 0);
EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate);
scalazPersistent = create(v -> scalaz.Heap.Empty$.MODULE$.<Integer> apply().insertAll(asScalaBuffer(v), SCALAZ_ORDER), asList(ELEMENTS), v -> v.size() == CONTAINER_SIZE);
fjava_persistent = create(v -> fj.data.PriorityQueue.<Integer> emptyInt().enqueue(v), List.of(ELEMENTS).map(v -> P.p(v, v)).toJavaList(), ELEMENTS.length, v -> v.toList().length() == CONTAINER_SIZE);
vavrPersistent = create(io.vavr.collection.PriorityQueue::of, ELEMENTS, ELEMENTS.length, v -> v.size() == CONTAINER_SIZE);
}
}
public static class Enqueue extends Base {
@Benchmark
@SuppressWarnings({ "Convert2streamapi", "ManualArrayToCollectionCopy" })
public Object java_mutable() {
final java.util.PriorityQueue<Integer> values = new java.util.PriorityQueue<>(CONTAINER_SIZE);
for (Integer element : ELEMENTS) {
values.add(element);
}
assert values.size() == CONTAINER_SIZE;
return values;
}
@Benchmark
@SuppressWarnings({ "Convert2streamapi", "ManualArrayToCollectionCopy" })
public Object java_blocking_mutable() {
final java.util.concurrent.PriorityBlockingQueue<Integer> values = new java.util.concurrent.PriorityBlockingQueue<>(CONTAINER_SIZE);
for (Integer element : ELEMENTS) {
values.add(element);
}
assert values.size() == CONTAINER_SIZE;
return values;
}
@Benchmark
public Object scala_mutable() {
final scala.collection.mutable.PriorityQueue<Integer> values = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING);
for (Integer element : ELEMENTS) {
values.$plus$eq(element);
}
assert values.size() == CONTAINER_SIZE;
return values;
}
@Benchmark
public Object scalaz_persistent() {
scalaz.Heap<Integer> values = scalaz.Heap.Empty$.MODULE$.apply();
for (Integer element : ELEMENTS) {
values = values.insert(element, SCALAZ_ORDER);
}
assert values.size() == CONTAINER_SIZE;
return values;
}
@Benchmark
public Object fjava_persistent() {
fj.data.PriorityQueue<Integer, Integer> values = fj.data.PriorityQueue.emptyInt();
for (Integer element : ELEMENTS) {
values = values.enqueue(element, element);
}
assert values.toList().length() == CONTAINER_SIZE;
return values;
}
@Benchmark
public Object vavr_persistent() {
io.vavr.collection.PriorityQueue<Integer> values = io.vavr.collection.PriorityQueue.empty();
for (Integer element : ELEMENTS) {
values = values.enqueue(element);
}
assert values.size() == CONTAINER_SIZE;
return values;
}
}
@SuppressWarnings("Convert2MethodRef")
public static class Dequeue extends Base {
@State(Scope.Thread)
public static class Initialized {
java.util.PriorityQueue<Integer> javaMutable = new java.util.PriorityQueue<>();
java.util.concurrent.PriorityBlockingQueue<Integer> javaBlockingMutable = new java.util.concurrent.PriorityBlockingQueue<>();
scala.collection.mutable.PriorityQueue<Integer> scalaMutable = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING);
@Setup(Level.Invocation)
public void initializeMutable(Base state) {
Collections.addAll(javaMutable, state.ELEMENTS);
Collections.addAll(javaBlockingMutable, state.ELEMENTS);
for (Integer element : state.ELEMENTS) {
scalaMutable.$plus$eq(element);
}
assert (javaMutable.size() == state.CONTAINER_SIZE)
&& (javaBlockingMutable.size() == state.CONTAINER_SIZE)
&& (scalaMutable.size() == state.CONTAINER_SIZE);
}
@TearDown(Level.Invocation)
public void tearDown() {
javaMutable.clear();
javaBlockingMutable.clear();
scalaMutable.clear();
}
}
@Benchmark
public Object java_mutable(Initialized state) {
final java.util.PriorityQueue<Integer> values = state.javaMutable;
int aggregate = 0;
for (; !values.isEmpty(); values.poll()) {
aggregate ^= values.peek();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object java_blocking_mutable(Initialized state) {
final java.util.concurrent.PriorityBlockingQueue<Integer> values = state.javaBlockingMutable;
int aggregate = 0;
for (; !values.isEmpty(); values.poll()) {
aggregate ^= values.peek();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object scala_mutable(Initialized state) {
final scala.collection.mutable.PriorityQueue<Integer> values = state.scalaMutable;
int aggregate = 0;
while (!values.isEmpty()) {
aggregate ^= values.dequeue();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object scalaz_persistent() {
scalaz.Heap<Integer> values = scalazPersistent;
int aggregate = 0;
while (!values.isEmpty()) {
final scala.Tuple2<Integer, scalaz.Heap<Integer>> uncons = values.uncons().get();
aggregate ^= uncons._1;
values = uncons._2;
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object fjava_persistent() {
fj.data.PriorityQueue<Integer, Integer> values = fjava_persistent;
int aggregate = 0;
while (!values.isEmpty()) {
aggregate ^= values.top().some()._1();
values = values.dequeue();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object vavr_persistent() {
io.vavr.collection.PriorityQueue<Integer> values = vavrPersistent;
int aggregate = 0;
while (!values.isEmpty()) {
final Tuple2<Integer, io.vavr.collection.PriorityQueue<Integer>> dequeue = values.dequeue();
aggregate ^= dequeue._1;
values = dequeue._2;
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
}
@SuppressWarnings("Convert2MethodRef")
public static class Sort extends Base {
@Benchmark
@SuppressWarnings("ManualArrayToCollectionCopy")
public Object java_mutable() {
final java.util.PriorityQueue<Integer> values = new java.util.PriorityQueue<>(CONTAINER_SIZE);
for (Integer element : ELEMENTS) {
values.add(element);
}
assert values.size() == CONTAINER_SIZE;
int aggregate = 0;
for (; !values.isEmpty(); values.poll()) {
aggregate ^= values.peek();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
@SuppressWarnings("ManualArrayToCollectionCopy")
public Object java_blocking_mutable() {
final java.util.concurrent.PriorityBlockingQueue<Integer> values = new java.util.concurrent.PriorityBlockingQueue<>(CONTAINER_SIZE);
for (Integer element : ELEMENTS) {
values.add(element);
}
assert values.size() == CONTAINER_SIZE;
int aggregate = 0;
for (; !values.isEmpty(); values.poll()) {
aggregate ^= values.peek();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
@SuppressWarnings("ManualArrayToCollectionCopy")
public Object java_treeset_mutable() {
io.vavr.collection.TreeMap<Integer, io.vavr.collection.List<Integer>> values = io.vavr.collection.TreeMap.empty();
for (Integer element : ELEMENTS) {
final io.vavr.collection.List<Integer> vs = values.get(element).getOrElse(io.vavr.collection.List.empty()).prepend(element);
values = values.put(element, vs);
}
assert values.values().map(Traversable::size).sum().intValue() == CONTAINER_SIZE;
int aggregate = 0;
while (!values.isEmpty()) {
final Tuple2<Integer, io.vavr.collection.List<Integer>> min = values.head();
for (Integer integer : min._2) {
aggregate ^= integer;
}
values = values.remove(min._1);
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object scala_mutable() {
scala.collection.mutable.PriorityQueue<Integer> values = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING);
for (Integer element : ELEMENTS) {
values = values.$plus$eq(element);
}
assert values.size() == CONTAINER_SIZE;
int aggregate = 0;
while (!values.isEmpty()) {
aggregate ^= values.dequeue();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object scalaz_persistent() {
scalaz.Heap<Integer> values = scalaz.Heap.Empty$.MODULE$.apply();
for (Integer element : ELEMENTS) {
values = values.insert(element, SCALAZ_ORDER);
}
assert values.size() == CONTAINER_SIZE;
int aggregate = 0;
while (!values.isEmpty()) {
final scala.Tuple2<Integer, Heap<Integer>> uncons = values.uncons().get();
aggregate ^= uncons._1;
values = uncons._2;
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object fjava_persistent() {
fj.data.PriorityQueue<Integer, Integer> values = fj.data.PriorityQueue.emptyInt();
for (Integer element : ELEMENTS) {
values = values.enqueue(element, element);
}
assert values.toList().length() == CONTAINER_SIZE;
int aggregate = 0;
while (!values.isEmpty()) {
aggregate ^= values.top().some()._1();
values = values.dequeue();
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
@Benchmark
public Object vavr_persistent() {
io.vavr.collection.PriorityQueue<Integer> values = io.vavr.collection.PriorityQueue.of(ELEMENTS);
assert values.size() == CONTAINER_SIZE;
int aggregate = 0;
while (!values.isEmpty()) {
final Tuple2<Integer, io.vavr.collection.PriorityQueue<Integer>> dequeue = values.dequeue();
aggregate ^= dequeue._1;
values = dequeue._2;
}
assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE);
return values;
}
}
}