Clean up use of Augmentation generics
[yangtools.git] / benchmarks / src / main / java / org / opendaylight / yangtools / yang / data / impl / tree / InMemoryDataTreeBenchmark.java
index a9171687cfc29b5aed112cc81651abc9f0817daf..9dd4a0b4ba4cc47a558c85938f01f8d6fd939517 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  */
 package org.opendaylight.yangtools.yang.data.impl.tree;
 
-import java.io.IOException;
+import com.google.common.collect.Streams;
+import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.*;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.openjdk.jmh.annotations.*;
+import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.tree.api.CursorAwareDataTreeModification;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+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.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
 import org.openjdk.jmh.runner.Runner;
 import org.openjdk.jmh.runner.RunnerException;
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.options.OptionsBuilder;
 
 /**
- * Benchmarking of InMemoryDataTree performance.
- *
- * JMH is used for microbenchmarking.
- *
- * @author Lukas Sedlak <lsedlak@cisco.com>
+ * Benchmarking of InMemoryDataTree performance. JMH is used for microbenchmarking.
  *
+ * @author Lukas Sedlak &lt;lsedlak@cisco.com&gt;
  * @see <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a>
  */
 @State(Scope.Thread)
 @BenchmarkMode(Mode.AverageTime)
 @OutputTimeUnit(TimeUnit.MILLISECONDS)
+@Fork(1)
 public class InMemoryDataTreeBenchmark {
 
+    private static final int WARMUP_ITERATIONS = 10;
+    private static final int MEASUREMENT_ITERATIONS = 10;
+
     private static final int OUTER_LIST_100K = 100000;
     private static final int OUTER_LIST_50K = 50000;
     private static final int OUTER_LIST_10K = 10000;
 
-    private static final YangInstanceIdentifier[] OUTER_LIST_100K_PATHS = initOuterListPaths(OUTER_LIST_100K);
-    private static final YangInstanceIdentifier[] OUTER_LIST_50K_PATHS = initOuterListPaths(OUTER_LIST_50K);
-    private static final YangInstanceIdentifier[] OUTER_LIST_10K_PATHS = initOuterListPaths(OUTER_LIST_10K);
+    private static final NodeIdentifierWithPredicates[] OUTER_LIST_IDS = Streams.mapWithIndex(
+        IntStream.range(0, OUTER_LIST_100K),
+        (i, index) -> NodeIdentifierWithPredicates.of(BenchmarkModel.OUTER_LIST_QNAME, BenchmarkModel.ID_QNAME, i))
+            .toArray(NodeIdentifierWithPredicates[]::new);
 
-    private static YangInstanceIdentifier[] initOuterListPaths(final int outerListPathsCount) {
-        final YangInstanceIdentifier[] paths = new YangInstanceIdentifier[outerListPathsCount];
-
-        for (int outerListKey = 0; outerListKey < outerListPathsCount; ++outerListKey) {
-            paths[outerListKey] = YangInstanceIdentifier.builder(BenchmarkModel.OUTER_LIST_PATH)
-                .nodeWithKey(BenchmarkModel.OUTER_LIST_QNAME, BenchmarkModel.ID_QNAME, outerListKey)
-                .build();
-        }
-        return paths;
-    }
+    private static final YangInstanceIdentifier[] OUTER_LIST_PATHS = Arrays.stream(OUTER_LIST_IDS)
+            .map(id -> BenchmarkModel.OUTER_LIST_PATH.node(id).toOptimized())
+            .toArray(YangInstanceIdentifier[]::new);
 
+    private static final MapNode EMPTY_OUTER_LIST = ImmutableNodes.newSystemMapBuilder()
+        .withNodeIdentifier(BenchmarkModel.OUTER_LIST)
+        .build();
     private static final MapNode ONE_ITEM_INNER_LIST = initInnerListItems(1);
     private static final MapNode TWO_ITEM_INNER_LIST = initInnerListItems(2);
     private static final MapNode TEN_ITEM_INNER_LIST = initInnerListItems(10);
 
     private static MapNode initInnerListItems(final int count) {
-        final CollectionNodeBuilder<MapEntryNode, MapNode> mapEntryBuilder = ImmutableNodes
-            .mapNodeBuilder(BenchmarkModel.INNER_LIST_QNAME);
-
-        for (int i = 1; i <= count; ++i) {
-            mapEntryBuilder
-                .withChild(ImmutableNodes.mapEntry(BenchmarkModel.INNER_LIST_QNAME, BenchmarkModel.NAME_QNAME, i));
+        final var mapEntryBuilder = ImmutableNodes.newSystemMapBuilder()
+            .withNodeIdentifier(BenchmarkModel.INNER_LIST);
+
+        for (int i = 0; i < count; ++i) {
+            mapEntryBuilder.withChild(ImmutableNodes.newMapEntryBuilder()
+                .withNodeIdentifier(
+                    NodeIdentifierWithPredicates.of(BenchmarkModel.INNER_LIST_QNAME, BenchmarkModel.NAME_QNAME, i))
+                .withChild(ImmutableNodes.leafNode(BenchmarkModel.NAME_QNAME, i))
+                .build());
         }
 
         return mapEntryBuilder.build();
     }
 
-    private static final NormalizedNode<?, ?>[] OUTER_LIST_ONE_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_100K, ONE_ITEM_INNER_LIST);
-    private static final NormalizedNode<?, ?>[] OUTER_LIST_TWO_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_50K, TWO_ITEM_INNER_LIST);
-    private static final NormalizedNode<?, ?>[] OUTER_LIST_TEN_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_10K, TEN_ITEM_INNER_LIST);
-
-    private static NormalizedNode<?,?>[] initOuterListItems(int outerListItemsCount, MapNode innerList) {
-        final NormalizedNode<?,?>[] outerListItems = new NormalizedNode[outerListItemsCount];
-
-        for (int i = 0; i < outerListItemsCount; ++i) {
-            int outerListKey = i;
-            outerListItems[i] = ImmutableNodes.mapEntryBuilder(BenchmarkModel.OUTER_LIST_QNAME, BenchmarkModel.ID_QNAME, outerListKey)
-                .withChild(innerList).build();
-        }
-        return outerListItems;
+    private static final MapEntryNode[] OUTER_LIST_ONE_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_100K,
+        ONE_ITEM_INNER_LIST);
+    private static final MapEntryNode[] OUTER_LIST_TWO_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_50K,
+        TWO_ITEM_INNER_LIST);
+    private static final MapEntryNode[] OUTER_LIST_TEN_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_10K,
+        TEN_ITEM_INNER_LIST);
+
+    private static MapEntryNode[] initOuterListItems(final int outerListItemsCount, final MapNode innerList) {
+        return Arrays.stream(OUTER_LIST_IDS)
+            .limit(outerListItemsCount)
+            .map(id -> ImmutableNodes.newMapEntryBuilder().withNodeIdentifier(id).withChild(innerList).build())
+            .toArray(MapEntryNode[]::new);
     }
 
-    private SchemaContext schemaContext;
     private DataTree datastore;
 
-    public static void main(String... args) throws IOException, RunnerException {
+    public static void main(final String... args) throws RunnerException {
         Options opt = new OptionsBuilder()
             .include(".*" + InMemoryDataTreeBenchmark.class.getSimpleName() + ".*")
             .forks(1)
@@ -104,121 +116,134 @@ public class InMemoryDataTreeBenchmark {
 
     @Setup(Level.Trial)
     public void setup() throws DataValidationFailedException {
-        schemaContext = BenchmarkModel.createTestContext();
-        final InMemoryDataTreeFactory factory = InMemoryDataTreeFactory.getInstance();
-        datastore = factory.create();
-        datastore.setSchemaContext(schemaContext);
-        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
-        initTestNode(snapshot);
+        datastore = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION,
+            BenchmarkModel.createTestContext());
+
+        final DataTreeModification modification = begin();
+        modification.write(BenchmarkModel.TEST_PATH, ImmutableNodes.newContainerBuilder()
+            .withNodeIdentifier(BenchmarkModel.TEST)
+            .withChild(EMPTY_OUTER_LIST)
+            .build());
+        commit(modification);
     }
 
     @TearDown
     public void tearDown() {
-        schemaContext = null;
         datastore = null;
     }
 
-    private void initTestNode(final DataTreeSnapshot snapshot) throws DataValidationFailedException {
-        final DataTreeModification modification = snapshot.newModification();
-        final YangInstanceIdentifier testPath = YangInstanceIdentifier.builder(BenchmarkModel.TEST_PATH)
-            .build();
-
-        modification.write(testPath, provideOuterListNode());
-        datastore.validate(modification);
-        final DataTreeCandidate candidate = datastore.prepare(modification);
-        datastore.commit(candidate);
+    @Benchmark
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write100KSingleNodeWithOneInnerItemInOneCommitBenchmark() throws DataValidationFailedException {
+        final DataTreeModification modification = begin();
+        for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) {
+            modification.write(OUTER_LIST_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
+        }
+        commit(modification);
     }
 
-    private DataContainerChild<?, ?> provideOuterListNode() {
-        return ImmutableContainerNodeBuilder
-            .create()
-            .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(BenchmarkModel.TEST_QNAME))
-            .withChild(
-                ImmutableNodes.mapNodeBuilder(BenchmarkModel.OUTER_LIST_QNAME)
-                    .build()).build();
+    @Benchmark
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write100KSingleNodeWithOneInnerItemInOneCommitCursorBenchmark() throws DataValidationFailedException {
+        final CursorAwareDataTreeModification modification = begin();
+        try (var cursor = modification.openCursor(BenchmarkModel.OUTER_LIST_PATH).orElseThrow()) {
+            for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) {
+                cursor.write(OUTER_LIST_IDS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
+            }
+        }
+        commit(modification);
     }
 
     @Benchmark
-    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
-    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
-    public void write100KSingleNodeWithOneInnerItemInOneCommitBenchmark() throws Exception {
-        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
-        final DataTreeModification modification = snapshot.newModification();
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write100KSingleNodeWithOneInnerItemInCommitPerWriteBenchmark() throws DataValidationFailedException {
         for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) {
-            modification.write(OUTER_LIST_100K_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
+            final DataTreeModification modification = begin();
+            modification.write(OUTER_LIST_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
+            commit(modification);
         }
-        datastore.validate(modification);
-        final DataTreeCandidate candidate = datastore.prepare(modification);
-        datastore.commit(candidate);
     }
 
     @Benchmark
-    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
-    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
-    public void write100KSingleNodeWithOneInnerItemInCommitPerWriteBenchmark() throws Exception {
-        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
-        for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) {
-            final DataTreeModification modification = snapshot.newModification();
-            modification.write(OUTER_LIST_100K_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
-            datastore.validate(modification);
-            final DataTreeCandidate candidate = datastore.prepare(modification);
-            datastore.commit(candidate);
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write50KSingleNodeWithTwoInnerItemsInOneCommitBenchmark() throws DataValidationFailedException {
+        final DataTreeModification modification = begin();
+        for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) {
+            modification.write(OUTER_LIST_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
         }
+        commit(modification);
     }
 
     @Benchmark
-    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
-    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
-    public void write50KSingleNodeWithTwoInnerItemsInOneCommitBenchmark() throws Exception {
-        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
-        final DataTreeModification modification = snapshot.newModification();
-        for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) {
-            modification.write(OUTER_LIST_50K_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write50KSingleNodeWithTwoInnerItemsInOneCommitCursorBenchmark() throws DataValidationFailedException {
+        final CursorAwareDataTreeModification modification = begin();
+        try (var cursor = modification.openCursor(BenchmarkModel.OUTER_LIST_PATH).orElseThrow()) {
+            for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) {
+                cursor.write(OUTER_LIST_IDS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
+            }
         }
-        datastore.validate(modification);
-        final DataTreeCandidate candidate = datastore.prepare(modification);
-        datastore.commit(candidate);
+        commit(modification);
     }
 
     @Benchmark
-    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
-    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
-    public void write50KSingleNodeWithTwoInnerItemsInCommitPerWriteBenchmark() throws Exception {
-        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write50KSingleNodeWithTwoInnerItemsInCommitPerWriteBenchmark() throws DataValidationFailedException {
         for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) {
-            final DataTreeModification modification = snapshot.newModification();
-            modification.write(OUTER_LIST_50K_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
-            datastore.validate(modification);
-            final DataTreeCandidate candidate = datastore.prepare(modification);
-            datastore.commit(candidate);
+            final DataTreeModification modification = begin();
+            modification.write(OUTER_LIST_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
+            commit(modification);
         }
     }
 
     @Benchmark
-    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
-    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
-    public void write10KSingleNodeWithTenInnerItemsInOneCommitBenchmark() throws Exception {
-        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
-        final DataTreeModification modification = snapshot.newModification();
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write10KSingleNodeWithTenInnerItemsInOneCommitBenchmark() throws DataValidationFailedException {
+        final DataTreeModification modification = begin();
         for (int outerListKey = 0; outerListKey < OUTER_LIST_10K; ++outerListKey) {
-            modification.write(OUTER_LIST_10K_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
+            modification.write(OUTER_LIST_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
         }
-        datastore.validate(modification);
-        final DataTreeCandidate candidate = datastore.prepare(modification);
-        datastore.commit(candidate);
+        commit(modification);
     }
 
     @Benchmark
-    @Warmup(iterations = 10, timeUnit = TimeUnit.MILLISECONDS)
-    @Measurement(iterations = 20, timeUnit = TimeUnit.MILLISECONDS)
-    public void write10KSingleNodeWithTenInnerItemsInCommitPerWriteBenchmark() throws Exception {
-        final DataTreeSnapshot snapshot = datastore.takeSnapshot();
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write10KSingleNodeWithTenInnerItemsInOneCommitCursorBenchmark() throws DataValidationFailedException {
+        final CursorAwareDataTreeModification modification = begin();
+        try (var cursor = modification.openCursor(BenchmarkModel.OUTER_LIST_PATH).orElseThrow()) {
+            for (int outerListKey = 0; outerListKey < OUTER_LIST_10K; ++outerListKey) {
+                cursor.write(OUTER_LIST_IDS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
+            }
+        }
+        commit(modification);
+    }
+
+    @Benchmark
+    @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
+    public void write10KSingleNodeWithTenInnerItemsInCommitPerWriteBenchmark() throws DataValidationFailedException {
         for (int outerListKey = 0; outerListKey < OUTER_LIST_10K; ++outerListKey) {
-            final DataTreeModification modification = snapshot.newModification();
-            modification.write(OUTER_LIST_10K_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
-            datastore.validate(modification);
-            final DataTreeCandidate candidate = datastore.prepare(modification);
-            datastore.commit(candidate);
+            final DataTreeModification modification = begin();
+            modification.write(OUTER_LIST_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
+            commit(modification);
         }
     }
+
+    private CursorAwareDataTreeModification begin() {
+        return (CursorAwareDataTreeModification) datastore.takeSnapshot().newModification();
+    }
+
+    private void commit(final DataTreeModification modification) throws DataValidationFailedException {
+        modification.ready();
+        datastore.validate(modification);
+        datastore.commit(datastore.prepare(modification));
+    }
 }