/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection; import io.vavr.JmhRunner; import org.junit.Test; import org.openjdk.jmh.annotations.*; import java.util.Objects; import java.util.Random; import static java.lang.String.valueOf; import static io.vavr.JmhRunner.create; import static io.vavr.collection.Collections.areEqual; public class CharSeqBenchmark { static final Array<Class<?>> CLASSES = Array.of( Head.class, Tail.class, Get.class, Update.class, Repeat.class, Prepend.class, Append.class, Iterate.class ); @Test public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } public static void main(java.lang.String... args) { JmhRunner.runDebugWithAsserts(CLASSES); JmhRunner.runNormalNoAsserts(CLASSES); } @State(Scope.Benchmark) public static class Base { @Param({ "10", "100", "1000" }) public int CONTAINER_SIZE; int EXPECTED_AGGREGATE; char[] ELEMENTS; java.lang.String javaPersistent; fj.data.LazyString fjavaPersistent; io.vavr.collection.CharSeq vavrPersistent; @Setup public void setup() { final Random random = new Random(0); ELEMENTS = new char[CONTAINER_SIZE]; for (int i = 0; i < CONTAINER_SIZE; i++) { ELEMENTS[i] = (char) random.nextInt(Character.MAX_VALUE); } EXPECTED_AGGREGATE = Iterator.ofAll(ELEMENTS).reduce((x, y) -> (char) JmhRunner.aggregate((int) x, (int) y)); javaPersistent = create(java.lang.String::new, ELEMENTS, ELEMENTS.length, v -> java.util.Arrays.equals(v.toCharArray(), ELEMENTS)); fjavaPersistent = create(fj.data.LazyString::str, javaPersistent, javaPersistent.length(), v -> Objects.equals(v.toStringEager(), javaPersistent)); vavrPersistent = create(io.vavr.collection.CharSeq::of, javaPersistent, javaPersistent.length(), v -> v.contentEquals(javaPersistent)); } } public static class Head extends Base { @Benchmark public Object java_persistent() { final Object head = javaPersistent.charAt(0); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object fjava_persistent() { final Object head = fjavaPersistent.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } @Benchmark public Object vavr_persistent() { final Object head = vavrPersistent.head(); assert Objects.equals(head, ELEMENTS[0]); return head; } } @SuppressWarnings("Convert2MethodRef") public static class Tail extends Base { @Benchmark public Object java_persistent() { java.lang.String values = javaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.substring(1); } assert values.isEmpty(); return values; } @Benchmark public Object fjava_persistent() { fj.data.LazyString values = fjavaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.tail(); } assert values.isEmpty(); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq 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_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaPersistent.charAt(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (int i = 0; i < ELEMENTS.length; i++) { aggregate ^= fjavaPersistent.charAt(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.charAt(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } public static class Update extends Base { final char replacement = '❤'; @Benchmark public Object java_persistent() { java.lang.String values = javaPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.substring(0, i) + replacement + values.substring(i + 1); } assert Array.ofAll(values.toCharArray()).forAll(c -> c == replacement); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq values = vavrPersistent; for (int i = 0; i < CONTAINER_SIZE; i++) { values = values.update(i, replacement); } assert values.forAll(c -> c == replacement); return values; } } public static class Repeat extends Base { final char value = '❤'; @Benchmark public Object vavr_persistent() { return CharSeq.of(value).repeat(CONTAINER_SIZE); } } public static class Prepend extends Base { @Benchmark public Object java_persistent() { java.lang.String values = ""; for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { values = ELEMENTS[i] + values; } assert Objects.equals(values, javaPersistent); return values; } @Benchmark public Object fjava_persistent() { fj.data.LazyString values = fj.data.LazyString.empty; for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { values = fj.data.LazyString.str(valueOf(ELEMENTS[i])).append(values); } assert Objects.equals(values.eval(), javaPersistent); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq values = io.vavr.collection.CharSeq.empty(); for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { values = values.prepend(ELEMENTS[i]); } assert values.contentEquals(vavrPersistent); return values; } } public static class Append extends Base { @Benchmark public Object java_persistent() { java.lang.String values = ""; for (char c : ELEMENTS) { values = values + c; } assert Objects.equals(values, javaPersistent); return values; } @Benchmark public Object fjava_persistent() { fj.data.LazyString values = fj.data.LazyString.empty; for (char c : ELEMENTS) { values = values.append(valueOf(c)); } assert areEqual(values.toStream(), vavrPersistent); return values; } @Benchmark public Object vavr_persistent() { io.vavr.collection.CharSeq values = io.vavr.collection.CharSeq.empty(); for (char c : ELEMENTS) { values = values.append(c); } assert values.contentEquals(vavrPersistent); return values; } } @SuppressWarnings("ForLoopReplaceableByForEach") public static class Iterate extends Base { @Benchmark public int java_persistent() { int aggregate = 0; for (int i = 0; i < CONTAINER_SIZE; i++) { aggregate ^= javaPersistent.charAt(i); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int fjava_persistent() { int aggregate = 0; for (final java.util.Iterator<Character> iterator = fjavaPersistent.toStream().iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } @Benchmark public int vavr_persistent() { int aggregate = 0; for (final Iterator<Character> iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { aggregate ^= iterator.next(); } assert aggregate == EXPECTED_AGGREGATE; return aggregate; } } }