From a89f463bf293b27257f3fdd0fcfe90e0742ff652 Mon Sep 17 00:00:00 2001 From: Lukas Sedlak Date: Tue, 9 Sep 2014 16:35:44 +0200 Subject: [PATCH] Created Benchmark for InMemoryDataStore Write Op Created Benchmark suite for testing InMemoryDataStore write operations. The benchmark is designed to measure efficiency of InMemoryDataStore write operations for scenarios: -100K Writes executed as One commit (100K items in one commit) of One outer list item with one inner list item -100K Writes executed as Each commit per Write (100K commits) of One outer list item with one inner list item -50K Writes executed as One commit (50K items in one commit) of One outer list item with two inner list items -50K Writes executed as Each commit per Write (50K commits) of One outer list item with two inner list items -10K Writes executed as One commit (10K items in one commit) of One outer list item with ten inner list items -10K Writes executed as Each commit per Write (10K commits) of One outer list item with ten inner list items Benchmark suite contains of three benchmark scenarios where InMemoryDataStore is instantiated with different combinations of executors. This will allow us to see how executor services has performance impact on DataStore write operations. The md-sal parent pom is extended with benchmarks profile. Change-Id: I04f6e4545445d5879d8de9785d7ba1a53ec007af Signed-off-by: Lukas Sedlak --- opendaylight/commons/opendaylight/pom.xml | 14 +- .../md-sal/benchmark-data-store/pom.xml | 72 +++++++ ...oryDatastoreWriteTransactionBenchmark.java | 196 ++++++++++++++++++ .../dom/store/benchmark/BenchmarkModel.java | 55 +++++ ...DataStoreWithExecutorServiceBenchmark.java | 65 ++++++ ...toreWithSameThreadedExecutorBenchmark.java | 59 ++++++ ...oryDataStoreWriteTransactionBenchmark.java | 50 +++++ .../main/resources/odl-datastore-test.yang | 42 ++++ opendaylight/md-sal/pom.xml | 9 + 9 files changed, 561 insertions(+), 1 deletion(-) create mode 100644 opendaylight/md-sal/benchmark-data-store/pom.xml create mode 100644 opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/AbstractInMemoryDatastoreWriteTransactionBenchmark.java create mode 100644 opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/BenchmarkModel.java create mode 100644 opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithExecutorServiceBenchmark.java create mode 100644 opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithSameThreadedExecutorBenchmark.java create mode 100644 opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWriteTransactionBenchmark.java create mode 100644 opendaylight/md-sal/benchmark-data-store/src/main/resources/odl-datastore-test.yang diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 2e817b97f3..d1ce63159b 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -211,7 +211,8 @@ 2013.09.07.4-SNAPSHOT 1.0.0-SNAPSHOT 0.6.2-SNAPSHOT - 0.12.0 + 0.12.0 + 0.9.7 @@ -2021,6 +2022,17 @@ xml runtime + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + diff --git a/opendaylight/md-sal/benchmark-data-store/pom.xml b/opendaylight/md-sal/benchmark-data-store/pom.xml new file mode 100644 index 0000000000..1af2287a10 --- /dev/null +++ b/opendaylight/md-sal/benchmark-data-store/pom.xml @@ -0,0 +1,72 @@ + + + + + sal-parent + org.opendaylight.controller + 1.1-SNAPSHOT + + 4.0.0 + + org.opendaylight.controller + benchmark-data-store + + + + org.opendaylight.yangtools + yang-data-impl + + + org.opendaylight.yangtools + yang-parser-impl + + + org.openjdk.jmh + jmh-core + + + org.openjdk.jmh + jmh-generator-annprocess + + + org.opendaylight.controller + sal-inmemory-datastore + + + + + + + org.codehaus.mojo + exec-maven-plugin + + test + java + + -classpath + + org.openjdk.jmh.Main + .* + + + + + run-benchmarks + integration-test + + exec + + + + + + + \ No newline at end of file diff --git a/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/AbstractInMemoryDatastoreWriteTransactionBenchmark.java b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/AbstractInMemoryDatastoreWriteTransactionBenchmark.java new file mode 100644 index 0000000000..aa5ef61ce4 --- /dev/null +++ b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/AbstractInMemoryDatastoreWriteTransactionBenchmark.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.benchmark; + +import java.util.concurrent.TimeUnit; +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore; +import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction; +import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +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.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.model.api.SchemaContext; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Warmup; + +/** + * @author Lukas Sedlak + */ +public abstract class AbstractInMemoryDatastoreWriteTransactionBenchmark { + + private static final int WARMUP_ITERATIONS = 20; + private static final int MEASUREMENT_ITERATIONS = 20; + + 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 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 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 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)); + } + 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; + } + + protected SchemaContext schemaContext; + protected InMemoryDOMDataStore domStore; + + abstract public void setUp() throws Exception; + + abstract public void tearDown(); + + protected void initTestNode() throws Exception { + final YangInstanceIdentifier testPath = YangInstanceIdentifier.builder(BenchmarkModel.TEST_PATH) + .build(); + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + writeTx.write(testPath, provideOuterListNode()); + + DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); + cohort.canCommit().get(); + cohort.preCommit().get(); + cohort.commit().get(); + } + + 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 write100KSingleNodeWithOneInnerItemInOneCommitBenchmark() throws Exception { + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) { + writeTx.write(OUTER_LIST_100K_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]); + } + DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); + cohort.canCommit().get(); + cohort.preCommit().get(); + cohort.commit().get(); + } + + @Benchmark + @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + public void write100KSingleNodeWithOneInnerItemInCommitPerWriteBenchmark() throws Exception { + for (int outerListKey = 0; outerListKey < OUTER_LIST_100K; ++outerListKey) { + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + writeTx.write(OUTER_LIST_100K_PATHS[outerListKey], OUTER_LIST_ONE_ITEM_INNER_LIST[outerListKey]); + + DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); + cohort.canCommit().get(); + cohort.preCommit().get(); + cohort.commit().get(); + } + } + + @Benchmark + @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + public void write50KSingleNodeWithTwoInnerItemsInOneCommitBenchmark() throws Exception { + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) { + writeTx.write(OUTER_LIST_50K_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]); + } + DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); + cohort.canCommit().get(); + cohort.preCommit().get(); + cohort.commit().get(); + } + + @Benchmark + @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + public void write50KSingleNodeWithTwoInnerItemsInCommitPerWriteBenchmark() throws Exception { + for (int outerListKey = 0; outerListKey < OUTER_LIST_50K; ++outerListKey) { + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + writeTx.write(OUTER_LIST_50K_PATHS[outerListKey], OUTER_LIST_TWO_ITEM_INNER_LIST[outerListKey]); + DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); + cohort.canCommit().get(); + cohort.preCommit().get(); + cohort.commit().get(); + } + } + + @Benchmark + @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + public void write10KSingleNodeWithTenInnerItemsInOneCommitBenchmark() throws Exception { + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + for (int outerListKey = 0; outerListKey < OUTER_LIST_10K; ++outerListKey) { + writeTx.write(OUTER_LIST_10K_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]); + } + DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); + cohort.canCommit().get(); + cohort.preCommit().get(); + cohort.commit().get(); + } + + @Benchmark + @Warmup(iterations = WARMUP_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + @Measurement(iterations = MEASUREMENT_ITERATIONS, timeUnit = TimeUnit.MILLISECONDS) + public void write10KSingleNodeWithTenInnerItemsInCommitPerWriteBenchmark() throws Exception { + for (int outerListKey = 0; outerListKey < OUTER_LIST_10K; ++outerListKey) { + DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction(); + writeTx.write(OUTER_LIST_10K_PATHS[outerListKey], OUTER_LIST_TEN_ITEM_INNER_LIST[outerListKey]); + DOMStoreThreePhaseCommitCohort cohort = writeTx.ready(); + cohort.canCommit().get(); + cohort.preCommit().get(); + cohort.commit().get(); + } + } +} diff --git a/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/BenchmarkModel.java b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/BenchmarkModel.java new file mode 100644 index 0000000000..024385b2a9 --- /dev/null +++ b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/BenchmarkModel.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.benchmark; + +import java.io.InputStream; +import java.util.Collections; +import java.util.Set; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; + +/** + * Benchmark Model class loads the odl-datastore-test.yang model from resources. + *
+ * This class serves as facilitator class which holds several references to initialized yang model as static final + * members. + * + * @author Lukas Sedlak + */ +public final class BenchmarkModel { + + public static final QName TEST_QNAME = QName + .create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13","test"); + public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list"); + public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list"); + public static final QName ID_QNAME = QName.create(TEST_QNAME, "id"); + public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name"); + private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang"; + + public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME); + public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build(); + + public static final InputStream getDatastoreBenchmarkInputStream() { + return getInputStream(DATASTORE_TEST_YANG); + } + + private static InputStream getInputStream(final String resourceName) { + return BenchmarkModel.class.getResourceAsStream(resourceName); + } + + public static SchemaContext createTestContext() { + YangParserImpl parser = new YangParserImpl(); + Set modules = parser.parseYangModelsFromStreams(Collections.singletonList( + getDatastoreBenchmarkInputStream())); + return parser.resolveSchemaContext(modules); + } +} diff --git a/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithExecutorServiceBenchmark.java b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithExecutorServiceBenchmark.java new file mode 100644 index 0000000000..4b9d66f4f2 --- /dev/null +++ b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithExecutorServiceBenchmark.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.benchmark; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore; +import org.opendaylight.yangtools.util.concurrent.SpecialExecutors; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +/** + * Benchmark for testing of performance of write operations for InMemoryDataStore. The instance + * of benchmark creates InMemoryDataStore with Data Change Listener Executor Service as BlockingBoundedFastThreadPool + * and DOM Store Executor Service as Blocking Bounded Fast Thread Pool. + * + * @see org.opendaylight.yangtools.util.concurrent.SpecialExecutors + * @see org.opendaylight.controller.md.sal.dom.store.benchmark.AbstractInMemoryDatastoreWriteTransactionBenchmark + * + * @author Lukas Sedlak + */ +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(1) +public class InMemoryDataStoreWithExecutorServiceBenchmark extends AbstractInMemoryDatastoreWriteTransactionBenchmark { + + private static final int MAX_DATA_CHANGE_EXECUTOR_POOL_SIZE = 20; + private static final int MAX_DATA_CHANGE_EXECUTOR_QUEUE_SIZE = 1000; + private static final int MAX_DATA_STORE_EXECUTOR_QUEUE_SIZE = 5000; + + @Setup(Level.Trial) + public void setUp() throws Exception { + final String name = "DS_BENCHMARK"; + final ExecutorService dataChangeListenerExecutor = SpecialExecutors.newBlockingBoundedFastThreadPool( + MAX_DATA_CHANGE_EXECUTOR_POOL_SIZE, MAX_DATA_CHANGE_EXECUTOR_QUEUE_SIZE, name + "-DCL"); + + final ExecutorService domStoreExecutor = SpecialExecutors.newBoundedSingleThreadExecutor( + MAX_DATA_STORE_EXECUTOR_QUEUE_SIZE, "DOMStore-" + name ); + + domStore = new InMemoryDOMDataStore(name, domStoreExecutor, + dataChangeListenerExecutor); + schemaContext = BenchmarkModel.createTestContext(); + domStore.onGlobalContextUpdated(schemaContext); + initTestNode(); + } + + @TearDown + public void tearDown() { + schemaContext = null; + domStore = null; + } +} diff --git a/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithSameThreadedExecutorBenchmark.java b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithSameThreadedExecutorBenchmark.java new file mode 100644 index 0000000000..6a0ceccd53 --- /dev/null +++ b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWithSameThreadedExecutorBenchmark.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.benchmark; + +import com.google.common.util.concurrent.MoreExecutors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore; +import org.opendaylight.yangtools.util.concurrent.SpecialExecutors; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; + +/** + * Benchmark for testing of performance of write operations for InMemoryDataStore. The instance + * of benchmark creates InMemoryDataStore with Data Change Listener Executor Service as Blocking Bounded Fast Thread Pool + * and DOM Store Executor Service as Same Thread Executor. + * + * @author Lukas Sedlak + */ +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(1) +public class InMemoryDataStoreWithSameThreadedExecutorBenchmark extends AbstractInMemoryDatastoreWriteTransactionBenchmark { + + private static final int MAX_DATA_CHANGE_EXECUTOR_POOL_SIZE = 20; + private static final int MAX_DATA_CHANGE_EXECUTOR_QUEUE_SIZE = 1000; + + @Setup(Level.Trial) + public void setUp() throws Exception { + final String name = "DS_BENCHMARK"; + final ExecutorService dataChangeListenerExecutor = SpecialExecutors.newBlockingBoundedFastThreadPool( + MAX_DATA_CHANGE_EXECUTOR_POOL_SIZE, MAX_DATA_CHANGE_EXECUTOR_QUEUE_SIZE, name + "-DCL"); + + domStore = new InMemoryDOMDataStore("SINGLE_THREADED_DS_BENCHMARK", MoreExecutors.sameThreadExecutor(), + dataChangeListenerExecutor); + schemaContext = BenchmarkModel.createTestContext(); + domStore.onGlobalContextUpdated(schemaContext); + initTestNode(); + } + + @TearDown + public void tearDown() { + schemaContext = null; + domStore = null; + } +} diff --git a/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWriteTransactionBenchmark.java b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWriteTransactionBenchmark.java new file mode 100644 index 0000000000..d3dda96af5 --- /dev/null +++ b/opendaylight/md-sal/benchmark-data-store/src/main/java/org/opendaylight/controller/md/sal/dom/store/benchmark/InMemoryDataStoreWriteTransactionBenchmark.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.md.sal.dom.store.benchmark; + +import com.google.common.util.concurrent.MoreExecutors; +import java.util.concurrent.TimeUnit; +import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.TearDown; + +/** + * Benchmark for testing of performance of write operations for InMemoryDataStore. The instance + * of benchmark creates InMemoryDataStore with Data Change Listener Executor Service as Same Thread Executor + * and DOM Store Executor Service as Same Thread Executor. + * + * @author Lukas Sedlak + */ +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(1) +public class InMemoryDataStoreWriteTransactionBenchmark extends AbstractInMemoryDatastoreWriteTransactionBenchmark { + + @Setup(Level.Trial) + public void setUp() throws Exception { + domStore = new InMemoryDOMDataStore("SINGLE_THREADED_DS_BENCHMARK", MoreExecutors.sameThreadExecutor(), + MoreExecutors.sameThreadExecutor()); + schemaContext = BenchmarkModel.createTestContext(); + domStore.onGlobalContextUpdated(schemaContext); + initTestNode(); + } + + @TearDown + public void tearDown() { + schemaContext = null; + domStore = null; + } +} diff --git a/opendaylight/md-sal/benchmark-data-store/src/main/resources/odl-datastore-test.yang b/opendaylight/md-sal/benchmark-data-store/src/main/resources/odl-datastore-test.yang new file mode 100644 index 0000000000..730ca17173 --- /dev/null +++ b/opendaylight/md-sal/benchmark-data-store/src/main/resources/odl-datastore-test.yang @@ -0,0 +1,42 @@ +module odl-datastore-test { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test"; + prefix "store-test"; + + revision "2014-03-13" { + description "Initial revision."; + } + + container test { + list outer-list { + key id; + leaf id { + type int32; + } + choice outer-choice { + case one { + leaf one { + type string; + } + } + case two-three { + leaf two { + type string; + } + leaf three { + type string; + } + } + } + list inner-list { + key name; + leaf name { + type int32; + } + leaf value { + type string; + } + } + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index ce830eaa62..71a0de9939 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -216,5 +216,14 @@ sal-binding-dom-it + + benchmarks + + false + + + benchmark-data-store + + \ No newline at end of file -- 2.36.6