2 * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.mdsal.dom.broker.test;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertTrue;
13 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
14 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL;
16 import org.opendaylight.mdsal.dom.broker.test.util.TestModel;
18 import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataStore;
19 import org.opendaylight.mdsal.dom.spi.store.DOMStore;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.mdsal.dom.broker.AbstractDOMDataBroker;
22 import org.opendaylight.mdsal.dom.broker.SerializedDOMDataBroker;
23 import org.opendaylight.mdsal.dom.api.DOMDataReadTransaction;
24 import org.opendaylight.mdsal.dom.api.DOMDataReadWriteTransaction;
25 import com.google.common.base.Optional;
26 import com.google.common.collect.ImmutableMap;
27 import com.google.common.util.concurrent.Futures;
28 import com.google.common.util.concurrent.ListenableFuture;
29 import com.google.common.util.concurrent.ListeningExecutorService;
30 import com.google.common.util.concurrent.MoreExecutors;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.concurrent.Callable;
34 import java.util.concurrent.Executors;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
39 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
40 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 public class DOMBrokerPerformanceTest {
46 private static final Logger log = LoggerFactory.getLogger(DOMBrokerPerformanceTest.class);
48 private static NormalizedNode<?, ?> outerList(final int i) {
49 return ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, i);
52 private static YangInstanceIdentifier outerListPath(final int i) {
53 return YangInstanceIdentifier.builder(TestModel.OUTER_LIST_PATH)//
54 .nodeWithKey(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, i) //
58 private SchemaContext schemaContext;
59 private AbstractDOMDataBroker domBroker;
61 private static <V> V measure(final String name, final Callable<V> callable) throws Exception {
62 // TODO Auto-generated method stub
63 log.debug("Measurement:{} Start", name);
64 long startNano = System.nanoTime();
66 return callable.call();
68 long endNano = System.nanoTime();
69 log.info("Measurement:\"{}\" Time:{} ms", name, (endNano - startNano) / 1000000.0d);
74 public void setupStore() {
75 InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", MoreExecutors.newDirectExecutorService());
76 InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", MoreExecutors.newDirectExecutorService());
77 schemaContext = TestModel.createTestContext();
79 operStore.onGlobalContextUpdated(schemaContext);
80 configStore.onGlobalContextUpdated(schemaContext);
82 ImmutableMap<LogicalDatastoreType, DOMStore> stores = ImmutableMap.<LogicalDatastoreType, DOMStore> builder() //
83 .put(CONFIGURATION, configStore) //
84 .put(OPERATIONAL, operStore) //
86 ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
87 domBroker = new SerializedDOMDataBroker(stores, executor);
91 public void testPerformance() throws Exception {
92 measure("Test Suite (all tests)", new Callable<Void>() {
95 public Void call() throws Exception {
96 smallTestSuite(10, 1000);
97 //smallTestSuite(10, 100);
98 smallTestSuite(100, 100);
99 //smallTestSuite(100, 100);
100 //smallTestSuite(1000, 10);
101 smallTestSuite(1000, 10);
102 //smallTestSuite(1000, 1000);
108 private void smallTestSuite(final int txNum, final int innerListWriteNum) throws Exception {
109 measure("TestSuite (Txs:" + txNum + " innerWrites:" + innerListWriteNum + ")", new Callable<Void>() {
112 public Void call() throws Exception {
113 measureOneTransactionTopContainer();
114 measureSeparateWritesOneLevel(txNum, innerListWriteNum);
120 private void measureSeparateWritesOneLevel(final int txNum, final int innerNum) throws Exception {
121 final List<DOMDataReadWriteTransaction> transactions = measure("Txs:"+ txNum + " Allocate",
122 new Callable<List<DOMDataReadWriteTransaction>>() {
124 public List<DOMDataReadWriteTransaction> call() throws Exception {
125 List<DOMDataReadWriteTransaction> builder = new ArrayList<>(txNum);
126 for (int i = 0; i < txNum; i++) {
127 DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
128 builder.add(writeTx);
133 assertEquals(txNum, transactions.size());
134 measure("Txs:"+ txNum + " Writes:1", new Callable<Void>() {
136 public Void call() throws Exception {
138 for (DOMDataReadWriteTransaction writeTx :transactions) {
139 // Writes /test/outer-list/i in writeTx
140 writeTx.put(OPERATIONAL, outerListPath(i), outerList(i));
147 measure("Txs:"+ txNum + " Writes:" + innerNum, new Callable<Void>() {
149 public Void call() throws Exception {
151 for (DOMDataReadWriteTransaction writeTx :transactions) {
152 // Writes /test/outer-list/i in writeTx
153 YangInstanceIdentifier path = YangInstanceIdentifier.builder(outerListPath(i))
154 .node(TestModel.INNER_LIST_QNAME).build();
155 writeTx.put(OPERATIONAL, path, ImmutableNodes.mapNodeBuilder(TestModel.INNER_LIST_QNAME).build());
156 for (int j = 0; j < innerNum; j++) {
157 YangInstanceIdentifier innerPath = YangInstanceIdentifier.builder(path)
158 .nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, String.valueOf(j))
163 ImmutableNodes.mapEntry(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME,
172 measure("Txs:" + txNum + " Submit, Finish", new Callable<Void>() {
174 public Void call() throws Exception {
175 List<ListenableFuture<?>> allFutures = measure(txNum + " Submits",
176 new Callable<List<ListenableFuture<?>>>() {
178 public List<ListenableFuture<?>> call() throws Exception {
179 List<ListenableFuture<?>> builder = new ArrayList<>(txNum);
180 for (DOMDataReadWriteTransaction tx :transactions) {
181 builder.add(tx.submit());
186 Futures.allAsList(allFutures).get();
191 final DOMDataReadTransaction readTx = measure("Txs:1 (ro), Allocate", new Callable<DOMDataReadTransaction>() {
193 public DOMDataReadTransaction call() throws Exception {
194 return domBroker.newReadOnlyTransaction();
200 measure("Txs:1 (ro) Reads:" + txNum + " (1-level)" , new Callable<Void>() {
202 public Void call() throws Exception {
203 for (int i = 0; i < txNum; i++) {
204 ListenableFuture<Optional<NormalizedNode<?, ?>>> potential = readTx.read(OPERATIONAL,
206 assertTrue("outerList/" + i, potential.get().isPresent());
212 measure("Txs:1 (ro) Reads:" + txNum * innerNum + " (2-level)", new Callable<Void>() {
214 public Void call() throws Exception {
215 for (int i = 0; i < txNum; i++) {
216 for (int j = 0; j < innerNum; j++) {
217 YangInstanceIdentifier path = YangInstanceIdentifier
218 .builder(outerListPath(i))
220 .node(TestModel.INNER_LIST_QNAME)
221 .nodeWithKey(TestModel.INNER_LIST_QNAME, TestModel.NAME_QNAME, String.valueOf(j))
223 ListenableFuture<Optional<NormalizedNode<?, ?>>> potential = readTx.read(OPERATIONAL, path);
224 assertTrue("outer-list/" + i + "/inner-list/" + j, potential.get().isPresent());
232 private void measureOneTransactionTopContainer() throws Exception {
234 final DOMDataReadWriteTransaction writeTx = measure("Txs:1 Allocate", new Callable<DOMDataReadWriteTransaction>() {
236 public DOMDataReadWriteTransaction call() throws Exception {
237 return domBroker.newReadWriteTransaction();
241 measure("Txs:1 Write", new Callable<Void>() {
243 public Void call() throws Exception {
244 writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
245 writeTx.put(OPERATIONAL, TestModel.OUTER_LIST_PATH,
246 ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME).build());
251 measure("Txs:1 Reads:1", new Callable<Void>() {
253 public Void call() throws Exception {
254 // Reads /test in writeTx
255 ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(OPERATIONAL,
256 TestModel.TEST_PATH);
257 assertTrue(writeTxContainer.get().isPresent());
262 measure("Txs:1 Reads:1", new Callable<Void>() {
264 public Void call() throws Exception {
265 // Reads /test in writeTx
266 ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(OPERATIONAL,
267 TestModel.TEST_PATH);
268 assertTrue(writeTxContainer.get().isPresent());
273 measure("Txs:1 Submit, Finish", new Callable<Void>() {
275 public Void call() throws Exception {
276 measure("Txs:1 Submit", new Callable<ListenableFuture<?>>() {
278 public ListenableFuture<?> call() throws Exception {
279 return writeTx.submit();