/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import java.util.ArrayList; import java.util.Objects; import static java.util.Arrays.asList; import static io.vavr.JmhRunner.create; import static io.vavr.JmhRunner.getRandomValues; import static io.vavr.collection.Collections.areEqual; public class ArrayBenchmark { static final Array<Class<?>> CLASSES = Array.of( Create.class, Head.class, Tail.class, Get.class, Update.class, Prepend.class, Append.class, Iterate.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(String... args) { JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({ "10", "100", "1000" }) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; Integer[] ELEMENTS; java.util.ArrayList<Integer> javaMutable; fj.data.Array<Integer> fjavaMutable; io.vavr.collection.Array<Integer> vavrPersistent; @Setup public void setup() { ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate); javaMutable = create(java.util.ArrayList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); fjavaMutable = create(fj.data.Array::array, ELEMENTS, ELEMENTS.length, v -> areEqual(v, asList(ELEMENTS))); vavrPersistent = create(io.vavr.collection.Array::ofAll, javaMutable, v -> areEqual(v, javaMutable)); } } public static class Create extends Base { @Benchmark public Object java_mutable() { final ArrayList<Integer> values = new ArrayList<>(javaMutable); assert areEqual(values, javaMutable); return values; } @Benchmark public Object fjava_persistent() { final fj.data.Array<Integer> values = fj.data.Array.iterableArray(javaMutable); assert areEqual(values, fjavaMutable); return values; } @Benchmark public Object vavr_persistent() { final io.vavr.collection.Array<Integer> values = io.vavr.collection.Array.ofAll(javaMutable); assert areEqual(values, vavrPersistent); return values.head(); } } public static class Head extends Base { @Benchmark public Object java_mutable() { final Object head = javaMutable.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object fjava_mutable() { final Object head = fjavaMutable.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent() { final Object head = vavrPersistent.get(0); assert Objects.equals(head, ELEMENTS[0]); return head; } } @SuppressWarnings("Convert2MethodRef") public static class Tail extends Base { @State(Scope.Thread) public static class Initialized { final java.util.ArrayList<Integer> javaMutable = new java.util.ArrayList<>(); @Setup(Level.Invocation) public void initializeMutable(Base state) { java.util.Collections.addAll(javaMutable, state.ELEMENTS); assert areEqual(javaMutable, asList(state.ELEMENTS)); } @TearDown(Level.Invocation) public void tearDown() { javaMutable.clear(); } } @Benchmark public Object java_mutable(Initialized state) { final java.util.ArrayList<Integer> values = state.javaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values.remove(0); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array<Integer> values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } } public static class Get extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_mutable() { int aggregate = 0; for (int i = 0; i < ELEMENTS.length; i++) { aggregate ^= fjavaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= vavrPersistent.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } public static class Update extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList<Integer> values = javaMutable; for (int i = 0; i < CONTAINER_SIZE; i++) { values.set(i, 0); } assert Iterator.ofAll(values).forAll(e -> e == 0); return javaMutable; } @Benchmark public Object fjava_mutable() { final fj.data.Array<Integer> values = fjavaMutable; for (int i = 0; i < ELEMENTS.length; i++) { values.set(i, 0); } assert values.forall(e -> e == 0); return fjavaMutable; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array<Integer> values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.update(i, 0); } assert values.forAll(e -> e == 0); return values; } } public static class Prepend extends Base { @Benchmark public Object java_mutable() { final java.util.ArrayList<Integer> values = new java.util.ArrayList<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(0, element); } assert areEqual(List.ofAll(values).reverse(), javaMutable); return values; } @Benchmark public Object fjava_mutable() { fj.data.Array<Integer> values = fj.data.Array.empty(); for (Integer element : ELEMENTS) { values = fj.data.Array.array(element).append(values); } assert areEqual(values.reverse(), javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array<Integer> values = io.vavr.collection.Array.empty(); for (Integer element : ELEMENTS) { values = values.prepend(element); } assert areEqual(values.reverse(), javaMutable); return values; } } public static class Append extends Base { @SuppressWarnings("ManualArrayToCollectionCopy") @Benchmark public Object java_mutable() { final java.util.ArrayList<Integer> values = new java.util.ArrayList<>(CONTAINER_SIZE); for (Integer element : ELEMENTS) { values.add(element); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object fjava_mutable() { fj.data.Array<Integer> values = fj.data.Array.empty(); for (Integer element : ELEMENTS) { values = values.append(fj.data.Array.array(element)); } assert areEqual(values, javaMutable); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.Array<Integer> values = io.vavr.collection.Array.empty(); for (Integer element : ELEMENTS) { values = values.append(element); } assert areEqual(values, javaMutable); return values; } } @SuppressWarnings("ForLoopReplaceableByForEach") public static class Iterate extends Base { @Benchmark public int java_mutable() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaMutable.get(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_mutable() { int aggregate = 0; for (final java.util.Iterator<Integer> iterator = fjavaMutable.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final Iterator<Integer> iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } }