Fix benchmark compilation and runtime
[yangtools.git] / benchmarks / src / main / java / org / opendaylight / yangtools / yang / data / impl / tree / InMemoryDataTreeBenchmark.java
1 /**
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.data.impl.tree;
9
10 import java.io.IOException;
11 import java.util.concurrent.TimeUnit;
12 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
13 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
14 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
15 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
16 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
17 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
18 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
19 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
20 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
21 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
22 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
23 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
24 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
25 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
26 import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
27 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
29 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
30 import org.openjdk.jmh.annotations.Benchmark;
31 import org.openjdk.jmh.annotations.BenchmarkMode;
32 import org.openjdk.jmh.annotations.Fork;
33 import org.openjdk.jmh.annotations.Level;
34 import org.openjdk.jmh.annotations.Measurement;
35 import org.openjdk.jmh.annotations.Mode;
36 import org.openjdk.jmh.annotations.OutputTimeUnit;
37 import org.openjdk.jmh.annotations.Scope;
38 import org.openjdk.jmh.annotations.Setup;
39 import org.openjdk.jmh.annotations.State;
40 import org.openjdk.jmh.annotations.TearDown;
41 import org.openjdk.jmh.annotations.Warmup;
42 import org.openjdk.jmh.runner.Runner;
43 import org.openjdk.jmh.runner.RunnerException;
44 import org.openjdk.jmh.runner.options.Options;
45 import org.openjdk.jmh.runner.options.OptionsBuilder;
46
47 /**
48  * Benchmarking of InMemoryDataTree performance.
49  *
50  * JMH is used for microbenchmarking.
51  *
52  * @author Lukas Sedlak <lsedlak@cisco.com>
53  *
54  * @see <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a>
55  */
56 @State(Scope.Thread)
57 @BenchmarkMode(Mode.AverageTime)
58 @OutputTimeUnit(TimeUnit.MILLISECONDS)
59 @Fork(1)
60 public class InMemoryDataTreeBenchmark {
61
62     private static final int WARMUP_ITERATIONS = 20;
63     private static final int MEASUREMENT_ITERATIONS = 20;
64
65     private static final int OUTER_LIST_100K = 100000;
66     private static final int OUTER_LIST_50K = 50000;
67     private static final int OUTER_LIST_10K = 10000;
68
69     private static final YangInstanceIdentifier[] OUTER_LIST_100K_PATHS = initOuterListPaths(OUTER_LIST_100K);
70     private static final YangInstanceIdentifier[] OUTER_LIST_50K_PATHS = initOuterListPaths(OUTER_LIST_50K);
71     private static final YangInstanceIdentifier[] OUTER_LIST_10K_PATHS = initOuterListPaths(OUTER_LIST_10K);
72
73     private static YangInstanceIdentifier[] initOuterListPaths(final int outerListPathsCount) {
74         final YangInstanceIdentifier[] paths = new YangInstanceIdentifier[outerListPathsCount];
75
76         for (int outerListKey = 0; outerListKey < outerListPathsCount; ++outerListKey) {
77             paths[outerListKey] = YangInstanceIdentifier.builder(BenchmarkModel.OUTER_LIST_PATH)
78                 .nodeWithKey(BenchmarkModel.OUTER_LIST_QNAME, BenchmarkModel.ID_QNAME, outerListKey)
79                 .build();
80         }
81         return paths;
82     }
83
84     private static final MapNode ONE_ITEM_INNER_LIST = initInnerListItems(1);
85     private static final MapNode TWO_ITEM_INNER_LIST = initInnerListItems(2);
86     private static final MapNode TEN_ITEM_INNER_LIST = initInnerListItems(10);
87
88     private static MapNode initInnerListItems(final int count) {
89         final CollectionNodeBuilder<MapEntryNode, MapNode> mapEntryBuilder = ImmutableNodes
90             .mapNodeBuilder(BenchmarkModel.INNER_LIST_QNAME);
91
92         for (int i = 1; i <= count; ++i) {
93             mapEntryBuilder
94                 .withChild(ImmutableNodes.mapEntry(BenchmarkModel.INNER_LIST_QNAME, BenchmarkModel.NAME_QNAME, i));
95         }
96
97         return mapEntryBuilder.build();
98     }
99
100     private static final NormalizedNode<?, ?>[] OUTER_LIST_ONE_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_100K, ONE_ITEM_INNER_LIST);
101     private static final NormalizedNode<?, ?>[] OUTER_LIST_TWO_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_50K, TWO_ITEM_INNER_LIST);
102     private static final NormalizedNode<?, ?>[] OUTER_LIST_TEN_ITEM_INNER_LIST = initOuterListItems(OUTER_LIST_10K, TEN_ITEM_INNER_LIST);
103
104     private static NormalizedNode<?,?>[] initOuterListItems(final int outerListItemsCount, final MapNode innerList) {
105         final NormalizedNode<?,?>[] outerListItems = new NormalizedNode[outerListItemsCount];
106
107         for (int i = 0; i < outerListItemsCount; ++i) {
108             int outerListKey = i;
109             outerListItems[i] = ImmutableNodes.mapEntryBuilder(BenchmarkModel.OUTER_LIST_QNAME, BenchmarkModel.ID_QNAME, outerListKey)
110                 .withChild(innerList).build();
111         }
112         return outerListItems;
113     }
114
115     private SchemaContext schemaContext;
116     private DataTree datastore;
117
118     public static void main(final String... args) throws IOException, RunnerException {
119         Options opt = new OptionsBuilder()
120             .include(".*" + InMemoryDataTreeBenchmark.class.getSimpleName() + ".*")
121             .forks(1)
122             .build();
123
124         new Runner(opt).run();
125     }
126
127     @Setup(Level.Trial)
128     public void setup() throws DataValidationFailedException, SourceException, ReactorException {
129         schemaContext = BenchmarkModel.createTestContext();
130         final InMemoryDataTreeFactory factory = InMemoryDataTreeFactory.getInstance();
131         datastore = factory.create(DataTreeConfiguration.DEFAULT_CONFIGURATION);
132         datastore.setSchemaContext(schemaContext);
133         final DataTreeSnapshot snapshot = datastore.takeSnapshot();
134         initTestNode(snapshot);
135     }
136
137     @TearDown
138     public void tearDown() {
139         schemaContext = null;
140         datastore = null;
141     }
142
143     private void initTestNode(final DataTreeSnapshot snapshot) throws DataValidationFailedException {
144         final DataTreeModification modification = snapshot.newModification();
145         final YangInstanceIdentifier testPath = YangInstanceIdentifier.builder(BenchmarkModel.TEST_PATH)
146             .build();
147
148         modification.write(testPath, provideOuterListNode());
149         modification.ready();
150         datastore.validate(modification);
151         final DataTreeCandidate candidate = datastore.prepare(modification);
152         datastore.commit(candidate);
153     }
154
155     private static DataContainerChild<?, ?> provideOuterListNode() {
156         return ImmutableContainerNodeBuilder
157             .create()
158             .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(BenchmarkModel.TEST_QNAME))
159             .withChild(
160                 ImmutableNodes.mapNodeBuilder(BenchmarkModel.OUTER_LIST_QNAME)
161                     .build()).build();
162     }
163
164     @Benchmark
165     @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
166     @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
167     public void write100KSingleNodeWithOneInnerItemInOneCommitBenchmark() throws Exception {
168         final DataTreeSnapshot snapshot = datastore.takeSnapshot();
169         final DataTreeModification modification = snapshot.newModification();
170         for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) {
171             modification.write(OUTER_LIST_100K_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
172         }
173         modification.ready();
174         datastore.validate(modification);
175         final DataTreeCandidate candidate = datastore.prepare(modification);
176         datastore.commit(candidate);
177     }
178
179     @Benchmark
180     @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
181     @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
182     public void write100KSingleNodeWithOneInnerItemInCommitPerWriteBenchmark() throws Exception {
183         final DataTreeSnapshot snapshot = datastore.takeSnapshot();
184         for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) {
185             final DataTreeModification modification = snapshot.newModification();
186             modification.write(OUTER_LIST_100K_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]);
187             modification.ready();
188             datastore.validate(modification);
189             final DataTreeCandidate candidate = datastore.prepare(modification);
190             datastore.commit(candidate);
191         }
192     }
193
194     @Benchmark
195     @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
196     @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
197     public void write50KSingleNodeWithTwoInnerItemsInOneCommitBenchmark() throws Exception {
198         final DataTreeSnapshot snapshot = datastore.takeSnapshot();
199         final DataTreeModification modification = snapshot.newModification();
200         for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) {
201             modification.write(OUTER_LIST_50K_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
202         }
203         datastore.validate(modification);
204         modification.ready();
205         final DataTreeCandidate candidate = datastore.prepare(modification);
206         datastore.commit(candidate);
207     }
208
209     @Benchmark
210     @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
211     @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
212     public void write50KSingleNodeWithTwoInnerItemsInCommitPerWriteBenchmark() throws Exception {
213         final DataTreeSnapshot snapshot = datastore.takeSnapshot();
214         for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) {
215             final DataTreeModification modification = snapshot.newModification();
216             modification.write(OUTER_LIST_50K_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]);
217             datastore.validate(modification);
218             modification.ready();
219             final DataTreeCandidate candidate = datastore.prepare(modification);
220             datastore.commit(candidate);
221         }
222     }
223
224     @Benchmark
225     @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
226     @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
227     public void write10KSingleNodeWithTenInnerItemsInOneCommitBenchmark() throws Exception {
228         final DataTreeSnapshot snapshot = datastore.takeSnapshot();
229         final DataTreeModification modification = snapshot.newModification();
230         for (int outerListKey = 0; outerListKey < OUTER_LIST_10K; ++outerListKey) {
231             modification.write(OUTER_LIST_10K_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
232         }
233         datastore.validate(modification);
234         modification.ready();
235         final DataTreeCandidate candidate = datastore.prepare(modification);
236         datastore.commit(candidate);
237     }
238
239     @Benchmark
240     @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
241     @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS)
242     public void write10KSingleNodeWithTenInnerItemsInCommitPerWriteBenchmark() throws Exception {
243         final DataTreeSnapshot snapshot = datastore.takeSnapshot();
244         for (int outerListKey = 0; outerListKey < OUTER_LIST_10K; ++outerListKey) {
245             final DataTreeModification modification = snapshot.newModification();
246             modification.write(OUTER_LIST_10K_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]);
247             datastore.validate(modification);
248             modification.ready();
249             final DataTreeCandidate candidate = datastore.prepare(modification);
250             datastore.commit(candidate);
251         }
252     }
253 }