HONEYCOMB-443: fix benchmark after ODL Neon bump
[honeycomb.git] / infra / it / benchmark / src / main / java / io / fd / honeycomb / benchmark / data / DataBrokerOperReadBenchmark.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.benchmark.data;
18
19 import com.google.inject.AbstractModule;
20 import com.google.inject.Guice;
21 import com.google.inject.Injector;
22 import com.google.inject.Key;
23 import com.google.inject.Module;
24 import com.google.inject.multibindings.Multibinder;
25 import com.google.inject.name.Names;
26 import io.fd.honeycomb.benchmark.util.DataProvider;
27 import io.fd.honeycomb.benchmark.util.FileManager;
28 import io.fd.honeycomb.benchmark.util.StaticReader;
29 import io.fd.honeycomb.infra.distro.activation.ActivationConfig;
30 import io.fd.honeycomb.infra.distro.activation.ActiveModules;
31 import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
32 import io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule;
33 import io.fd.honeycomb.translate.read.Reader;
34 import io.fd.honeycomb.translate.read.ReaderFactory;
35 import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
36 import java.io.IOException;
37 import java.nio.file.Paths;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
41 import java.util.Optional;
42 import java.util.concurrent.ExecutionException;
43 import java.util.stream.Collectors;
44 import org.eclipse.jdt.annotation.NonNull;
45 import org.opendaylight.mdsal.binding.api.DataBroker;
46 import org.opendaylight.mdsal.binding.api.ReadTransaction;
47 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.ContainerWithList;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.ContainerWithListBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.SimpleContainer;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.container.with.list.ListInContainer;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.openjdk.jmh.annotations.*;
54 import org.openjdk.jmh.annotations.Scope;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 /**
59  * Measures the performance of CONFIG writes into BA DataBroker, backed by HC infrastructure and then NOOP writers.
60  */
61 /*
62  * Timeout for one run of benchmark method
63  * */
64 @Timeout(time = 1)
65
66 /*
67 * 20 warmup iterations, each will run for 1 second. Serves to get more real-life results, as jvm has many internal
68 * optimizations that takes time to create profiles for.
69 * */
70 @Warmup(iterations = 20, time = 1)
71
72 /*
73  100 measurement iteration, each will run for 1 second.
74  It means that there will be 100 iterations, each will run tested method for 1 second and see how many iterations were
75  possible
76  */
77 @Measurement(iterations = 100, time = 1)
78
79 /*
80 * An instance will be allocated for each thread running the given test.
81 * */
82 @State(Scope.Thread)
83
84 /*
85 * Control code runs on one jvm, benchmark runs on different one to have isolation
86 * */
87 @Fork(1)
88
89 /*
90 * Measuring Maximum throughput of operations
91 * */
92 @BenchmarkMode(Mode.Throughput)
93 public class DataBrokerOperReadBenchmark extends AbstractModule implements FileManager {
94
95     private static final Logger LOG = LoggerFactory.getLogger(DataBrokerOperReadBenchmark.class);
96
97     /*
98     * Type of data used in benchmark
99     * */
100     @Param({"OPERATIONAL"})
101     private LogicalDatastoreType dsType;
102
103     // Persistence does not make a difference when only reading operational
104     @Param({"false"})
105     private boolean persistence;
106
107     /*
108     * Data sample type used
109     * */
110     @Param({DataProvider.SIMPLE_CONTAINER, DataProvider.LIST_IN_CONTAINER, DataProvider.COMPLEX_LIST_IN_CONTAINER})
111     private String data;
112     private DataProvider dataProvider;
113
114     // Infra modules to load
115     private final Module[] modules = new Module[]{
116             new io.fd.honeycomb.infra.distro.schema.YangBindingProviderModule(),
117             new io.fd.honeycomb.infra.distro.schema.SchemaModule(),
118             new ConfigAndOperationalPipelineModule(),
119             new io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule(),
120             this};
121
122     private List<Reader<?, ?>> noopReaders = new ArrayList<>();
123     private DataBroker dataBroker;
124     private long counter = 0;
125     private @NonNull ReadTransaction tx;
126     private HoneycombConfiguration instance;
127
128     @Setup(Level.Iteration)
129     public void setup() {
130         LOG.info("Setting up");
131         dataProvider = DataProvider.from(data);
132         Injector injector = Guice.createInjector(modules);
133         final HoneycombConfiguration cfg = injector.getInstance(HoneycombConfiguration.class);
134         LOG.info("Configuration for Honeycomb: {}", cfg);
135         dataBroker = injector.getInstance(Key.get(DataBroker.class,
136                 Names.named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG)));
137         tx = dataBroker.newReadOnlyTransaction();
138     }
139
140     @TearDown(Level.Iteration)
141     public void tearDown() {
142         LOG.info("Tearing down after {} executions", counter);
143         counter = 0;
144         LOG.info("Reader invocations: {}", noopReaders);
145         noopReaders.clear();
146
147         tx.close();
148         tx = null;
149         dataBroker = null;
150         deleteFile(Paths.get(instance.peristConfigPath));
151         deleteFile(Paths.get(instance.peristContextPath));
152     }
153
154     @Benchmark
155     public void read() {
156         try {
157             tx.read(dsType, dataProvider.getId(counter++)).get();
158         } catch (InterruptedException | ExecutionException e) {
159             throw new RuntimeException("Read failed", e);
160         }
161     }
162
163     /**
164      * Inject custom modules e.g. configuration.
165      */
166     @Override
167     protected void configure() {
168         try {
169             instance = getHoneycombConfiguration(persistence);
170             bind(HoneycombConfiguration.class).toInstance(instance);
171             bind(ActivationConfig.class).toInstance(getActivationConfig());
172             bind(ActiveModules.class).toInstance(
173                     new ActiveModules(Arrays.stream(modules).map(Module::getClass).collect(Collectors.toSet())));
174         } catch (IOException e) {
175             throw new RuntimeException("Unable to prepare configuration", e);
176         }
177
178         final Multibinder<ReaderFactory> writeBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
179         writeBinder.addBinding().toInstance(registry -> {
180
181             switch (data) {
182                 case DataProvider.SIMPLE_CONTAINER: {
183                     addReader(registry, new StaticReader<>(
184                             InstanceIdentifier.create(SimpleContainer.class),
185                             DataProvider.from(DataProvider.SIMPLE_CONTAINER)));
186                     break;
187                 }
188                 case DataProvider.LIST_IN_CONTAINER: {
189                     registry.addStructuralReader(
190                             InstanceIdentifier.create(ContainerWithList.class), ContainerWithListBuilder.class);
191                     addReader(registry, new StaticReader<>(
192                             InstanceIdentifier.create(ContainerWithList.class).child(ListInContainer.class),
193                             DataProvider.from(DataProvider.LIST_IN_CONTAINER)));
194                     break;
195                 }
196                 case DataProvider.COMPLEX_LIST_IN_CONTAINER: {
197                     registry.addStructuralReader(
198                             InstanceIdentifier.create(ContainerWithList.class), ContainerWithListBuilder.class);
199                     addReader(registry, new StaticReader<>(
200                             InstanceIdentifier.create(ContainerWithList.class).child(ListInContainer.class),
201                             DataProvider.from(DataProvider.COMPLEX_LIST_IN_CONTAINER)));
202                     break;
203                 }
204             }
205         });
206     }
207
208     private void addReader(final ModifiableReaderRegistryBuilder registry, final Reader<?, ?> handler) {
209         noopReaders.add(handler);
210         registry.add(handler);
211     }
212
213     private static HoneycombConfiguration getHoneycombConfiguration(final boolean persistence) throws IOException {
214         final HoneycombConfiguration instance = new HoneycombConfiguration();
215         instance.persistConfig = Optional.of(Boolean.toString(persistence));
216         instance.persistContext = Optional.of(Boolean.toString(persistence));
217         instance.peristConfigPath = FileManager.INSTANCE.createTempFile("config").toString();
218         instance.peristContextPath = FileManager.INSTANCE.createTempFile("context").toString();
219         return instance;
220     }
221
222     private static ActivationConfig getActivationConfig() {
223         final ActivationConfig activationConfig = new ActivationConfig();
224         activationConfig.yangModulesIndexPath = "yang-mapping";
225         return activationConfig;
226     }
227 }