diff options
author | Jan Srnicek <jsrnicek@cisco.com> | 2017-01-31 10:00:51 +0100 |
---|---|---|
committer | Jan Srnicek <jsrnicek@cisco.com> | 2017-01-31 10:00:51 +0100 |
commit | 92afaeb4a959ea5a6a072fe3ed7a01088d703e0b (patch) | |
tree | fc98660011e75ca71f97c25e641638dce37158bd | |
parent | 60e463b17b05458c1f9a7fd72f9e99d71124eedf (diff) |
HONEYCOMB-293 - Memory benchmarking
Contains configuration for benchmarks:
- Honeycomb on rest(just infra, no data)
- Honeycomb with 1000 data nodes
- Honeycomb with 10000 data nodes
Each benchmark outputs two files:
- out_path_name-HeapMemoryUsage.csv
- out_path_name-NonHeapMemoryUsage.csv
Both files are in format :
committed,init,max,used
109576192,109051904,1525153792,12194752
Data sample sizes can be easily adjusted, just by changing
start parameter -DsampleSize
Change-Id: If6f9919307574237689326b4a38d410ec563200a
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
27 files changed, 1441 insertions, 2 deletions
diff --git a/infra/it/management/asciidoc/Readme.adoc b/infra/it/management/asciidoc/Readme.adoc new file mode 100644 index 000000000..89bbf65d3 --- /dev/null +++ b/infra/it/management/asciidoc/Readme.adoc @@ -0,0 +1,35 @@ += management + +This modules is used to enable JMX monitoring on honeycomb Instance. + += Tutorial +== Configure +To build honeycomb with management module incldued + + mvn clean install -DskipTests -Pmanagement + +After this management module must be included to honeycomb module configuration. +In /minimal-distribution/modules , just include fully qualified name of management module like so + + io.fd.honeycomb.management.jmx.HoneycombManagementModule + +This will start all necessary beans to allow jmx connections to honeycomb instance. +Also in logs , you will see all available JMX beans + +== Use + +To get any available JMX bean, +use interface *JMXBeanProvider* that defines utility method to get *JMXConnector* + + // get configured instance of jxm connection url according to HoneycombManagementConfig + @Inject JMXServiceUrl url; + + // creates JMX connector + final JMXConnector connector = getConnector(url); + // to get any available bean + final String beanType = "java.lang:type=Memory"; + final String beanName = "HeapMemoryUsage"; + final Object jmxBean = getJMXAttribute(connector, beanType, beanName); + + + diff --git a/infra/it/management/pom.xml b/infra/it/management/pom.xml new file mode 100644 index 000000000..0a8e97200 --- /dev/null +++ b/infra/it/management/pom.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (c) 2017 Cisco and/or its affiliates. + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at: + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>io.fd.honeycomb.common</groupId> + <artifactId>honeycomb-parent</artifactId> + <version>1.17.04-SNAPSHOT</version> + <relativePath>../../../common/honeycomb-parent</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <properties> + <jetty-jmx.version>9.3.11.v20160721</jetty-jmx.version> + </properties> + + <groupId>io.fd.honeycomb.it</groupId> + <artifactId>management</artifactId> + <version>1.17.04-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-jmx</artifactId> + <version>${jetty-jmx.version}</version> + </dependency> + + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>minimal-distribution</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/ConnectorServerProvider.java b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/ConnectorServerProvider.java new file mode 100644 index 000000000..625c63cb8 --- /dev/null +++ b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/ConnectorServerProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.management.jmx; + +import com.google.inject.Inject; +import io.fd.honeycomb.infra.distro.ProviderTrait; +import org.eclipse.jetty.jmx.ConnectorServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.management.remote.JMXServiceURL; + +/** + * Provides and start JMX connector server + * */ +public class ConnectorServerProvider extends ProviderTrait<ConnectorServer> { + + private static final Logger LOG = LoggerFactory.getLogger(ConnectorServerProvider.class); + + @Inject + private HoneycombManagementConfig config; + + @Inject + private JMXServiceURL jmxServiceUrl; + + @Override + protected ConnectorServer create() { + try { + final ConnectorServer connectorServer = new ConnectorServer(jmxServiceUrl, + "org.eclipse.jetty.jmx:name="+HoneycombManagementConfig.JXM_CONNECTOR_SERVER_NAME); + + LOG.info("Starting connector server {}", connectorServer); + connectorServer.doStart(); + + return connectorServer; + } catch (Exception e) { + throw new IllegalStateException("Unable to create jmx connector server", e); + } + } +} diff --git a/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/HoneycombManagementConfig.java b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/HoneycombManagementConfig.java new file mode 100644 index 000000000..2362b6f43 --- /dev/null +++ b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/HoneycombManagementConfig.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.management.jmx; + + +import net.jmob.guice.conf.core.BindConfig; +import net.jmob.guice.conf.core.InjectConfig; +import net.jmob.guice.conf.core.Syntax; + +import java.util.Optional; + +@BindConfig(value = "management", syntax = Syntax.JSON) +public class HoneycombManagementConfig { + + public static final String JMX_PROTOCOL = "rmi"; + public static final String JXM_CONNECTOR_SERVER_NAME = "rmi"; + + public static final String PROP_JMX_HOST = "jetty.jmxrmihost"; + public static final String PROP_JMX_PORT = "jetty.jmxrmiport"; + + + @InjectConfig(PROP_JMX_HOST) + private String jmxHost; + + @InjectConfig(PROP_JMX_PORT) + private String jmxPort; + + public String getJmxHost() { + return Optional.ofNullable(jmxHost).orElse("localhost"); + } + + public int getJmxPort() { + return Integer.parseInt(Optional.ofNullable(jmxPort).orElse("1099")); + } +} diff --git a/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/HoneycombManagementModule.java b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/HoneycombManagementModule.java new file mode 100644 index 000000000..bc75cd01f --- /dev/null +++ b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/HoneycombManagementModule.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.management.jmx; + + +import com.google.inject.AbstractModule; +import net.jmob.guice.conf.core.ConfigurationModule; +import org.eclipse.jetty.jmx.ConnectorServer; +import org.eclipse.jetty.jmx.MBeanContainer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.management.ObjectInstance; +import javax.management.remote.JMXServiceURL; +import java.lang.management.ManagementFactory; + +public class HoneycombManagementModule extends AbstractModule { + + private static final Logger LOG = LoggerFactory.getLogger(HoneycombManagementModule.class); + + @Override + protected void configure() { + install(ConfigurationModule.create()); + requestInjection(HoneycombManagementConfig.class); + bind(MBeanContainer.class).toInstance(new MBeanContainer(ManagementFactory.getPlatformMBeanServer())); + bind(JMXServiceURL.class).toProvider(JMXServiceUrlProvider.class); + // .asEagerSingleton(); will cause also start defined in provider + bind(ConnectorServer.class).toProvider(ConnectorServerProvider.class).asEagerSingleton(); + + showAvailableBeans(); + } + + /** + * Prints all available JMX beans + */ + protected static void showAvailableBeans() { + for (final ObjectInstance instance : ManagementFactory.getPlatformMBeanServer().queryMBeans(null, null)) { + LOG.info("MBean Found:"); + LOG.info("Class Name:{}", instance.getClassName()); + LOG.info("Object Name:{}", instance.getObjectName()); + LOG.info("****************************************"); + } + } +} diff --git a/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/JMXBeanProvider.java b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/JMXBeanProvider.java new file mode 100644 index 000000000..557acb464 --- /dev/null +++ b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/JMXBeanProvider.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.management.jmx; + +import javax.annotation.Nonnull; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import java.io.IOException; + +public interface JMXBeanProvider { + + /** + * Provides JMX connector to specified url + */ + default JMXConnector getConnector(@Nonnull final JMXServiceURL url) { + try { + return JMXConnectorFactory.connect(url); + } catch (IOException e) { + throw new IllegalStateException("Unable to create JMX connector", e); + } + } + + /** + * Requests specified jxm bean from provided connector + */ + default Object getJMXAttribute(@Nonnull final JMXConnector connector, @Nonnull final String beanType, + @Nonnull final String beanName) { + try { + return connector.getMBeanServerConnection().getAttribute(new ObjectName(beanType), beanName); + } catch (Exception e) { + throw new IllegalStateException( + String.format("Unable to query mbean of type %s, name %s", beanType, beanName), e); + } + } +} diff --git a/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/JMXServiceUrlProvider.java b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/JMXServiceUrlProvider.java new file mode 100644 index 000000000..1b9136501 --- /dev/null +++ b/infra/it/management/src/main/java/io/fd/honeycomb/management/jmx/JMXServiceUrlProvider.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.management.jmx; + +import com.google.inject.Inject; +import io.fd.honeycomb.infra.distro.ProviderTrait; + +import javax.management.remote.JMXServiceURL; +import java.net.MalformedURLException; + +/** + * Provides properly binded {@link JMXServiceURL} + */ +public class JMXServiceUrlProvider extends ProviderTrait<JMXServiceURL> { + + @Inject + private HoneycombManagementConfig config; + + @Override + protected JMXServiceURL create() { + try { + return new JMXServiceURL( + HoneycombManagementConfig.JMX_PROTOCOL, + config.getJmxHost(), + config.getJmxPort(), + "/jndi/rmi://" + config.getJmxHost() + ":" + config.getJmxPort() + "/jmxrmi"); + } catch (MalformedURLException e) { + throw new IllegalStateException("Unable to create JXM Service url", e); + } + } +} diff --git a/infra/it/management/src/main/resources/management.json b/infra/it/management/src/main/resources/management.json new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/infra/it/management/src/main/resources/management.json @@ -0,0 +1,2 @@ +{ +}
\ No newline at end of file diff --git a/infra/it/memory-benchmark-api/asciidoc/Readme.adoc b/infra/it/memory-benchmark-api/asciidoc/Readme.adoc new file mode 100644 index 000000000..c63073613 --- /dev/null +++ b/infra/it/memory-benchmark-api/asciidoc/Readme.adoc @@ -0,0 +1,5 @@ += memory-benchmark-api + +Overview of memory-benchmark-api + +Provides test models for honeycomb memory benchmark.
\ No newline at end of file diff --git a/infra/it/memory-benchmark-api/pom.xml b/infra/it/memory-benchmark-api/pom.xml new file mode 100644 index 000000000..8b92303ec --- /dev/null +++ b/infra/it/memory-benchmark-api/pom.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>api-parent</artifactId> + <groupId>io.fd.honeycomb.common</groupId> + <version>1.17.04-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <groupId>io.fd.honeycomb.it</groupId> + <artifactId>memory-benchmark-api</artifactId> + <version>1.17.04-SNAPSHOT</version> +</project>
\ No newline at end of file diff --git a/infra/it/memory-benchmark-api/src/main/yang/memory-benchmark.yang b/infra/it/memory-benchmark-api/src/main/yang/memory-benchmark.yang new file mode 100644 index 000000000..e01550659 --- /dev/null +++ b/infra/it/memory-benchmark-api/src/main/yang/memory-benchmark.yang @@ -0,0 +1,19 @@ +module memory-benchmark { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:memory:benchmark"; + prefix "mm-bench"; + + revision "2016-12-04" { + description "Memory benchmark test api"; + } + + container config-data { + list config-list { + key name; + leaf name { + type string; + } + } + } +}
\ No newline at end of file diff --git a/infra/it/memory-benchmark-scripts/pom.xml b/infra/it/memory-benchmark-scripts/pom.xml new file mode 100644 index 000000000..b6b29e5e2 --- /dev/null +++ b/infra/it/memory-benchmark-scripts/pom.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <!-- have to basically duplicate common-scripts, it cannot be used as parent because of jar packaging --> + + <properties> + <!-- groovy --> + <maven.groovy.version>2.0</maven.groovy.version> + <groovy.version>2.4.7</groovy.version> + <groovy.eclipse.compiler.version>2.9.2-01</groovy.eclipse.compiler.version> + <groovy.eclipse.batch.version>2.4.3-01</groovy.eclipse.batch.version> + </properties> + + <modelVersion>4.0.0</modelVersion> + <groupId>io.fd.honeycomb.it</groupId> + <artifactId>benchmark-scripts</artifactId> + <version>1.17.04-SNAPSHOT</version> + <packaging>jar</packaging> + + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <configuration> + <skip>true</skip> + <skipDeploy>true</skipDeploy> + </configuration> + </plugin> + </plugins> + </pluginManagement> + <plugins> + <plugin> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-compiler</artifactId> + <version>${groovy.eclipse.compiler.version}</version> + <extensions>true</extensions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <!-- 2.8.0-01 and later require maven-compiler-plugin 3.1 or higher --> + <configuration> + <compilerId>groovy-eclipse-compiler</compilerId> + </configuration> + <dependencies> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-compiler</artifactId> + <version>${groovy.eclipse.compiler.version}</version> + </dependency> + <!-- for 2.8.0-01 and later you must have an explicit dependency on groovy-eclipse-batch --> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-eclipse-batch</artifactId> + <version>${groovy.eclipse.batch.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-all</artifactId> + <version>${groovy.version}</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/infra/it/memory-benchmark-scripts/src/main/groovy/io/fd/honeycomb/benchmark/script/MemoryBenchmarkStartupScriptGenerator.groovy b/infra/it/memory-benchmark-scripts/src/main/groovy/io/fd/honeycomb/benchmark/script/MemoryBenchmarkStartupScriptGenerator.groovy new file mode 100644 index 000000000..1db656aca --- /dev/null +++ b/infra/it/memory-benchmark-scripts/src/main/groovy/io/fd/honeycomb/benchmark/script/MemoryBenchmarkStartupScriptGenerator.groovy @@ -0,0 +1,38 @@ +package io.fd.honeycomb.benchmark.script + +import groovy.text.SimpleTemplateEngine + +import java.nio.file.Files +import java.nio.file.Paths + +class MemoryBenchmarkStartupScriptGenerator { + + static final def STARTUP_SCRIPT_ON_REST_TEMPLATE = MemoryBenchmarkStartupScriptGenerator.getResource("/memoryBenchmarkScript") + static final def STARTUP_SCRIPT_NAME_BASE = "honeycomb-memory-footprint-benchmark-" + + static final def FOOTPRINT_TEST_CLASS = "io.fd.honeycomb.benchmark.memory.HoneycombFootprintTest" + + static final def OUTPUT_PATH_PARAM = "-DoutPath=\$(dirname \$0)/" + static final def SAMPLE_SIZE_PARAM = "-DsampleSize=" + + /** + * Generate script to run io.fd.honeycomb.benchmark.memory.HoneycombWithDataTest with provided params + * */ + public static void generateWithDataScript(project, log, String outputFileName, dataSampleSize) { + log.info "Binding execution script for with-data benchmark[output=${outputFileName},sampleSize=${dataSampleSize}]" + def scriptContent = new SimpleTemplateEngine().createTemplate(STARTUP_SCRIPT_ON_REST_TEMPLATE).make( + [ + "testParams" : "${OUTPUT_PATH_PARAM}${outputFileName}-${dataSampleSize} ${SAMPLE_SIZE_PARAM}${dataSampleSize}", + "testClass" : FOOTPRINT_TEST_CLASS + ]).toString() + flushScript(Paths.get(project.build.directory, "${STARTUP_SCRIPT_NAME_BASE}${dataSampleSize}"), scriptContent, log) + } + + private static flushScript(filePath, content,log) { + log.info "Saving script to path ${filePath}" + def file = Files.createFile(filePath).toFile() + + file.text = content + file.setExecutable(true) + } +} diff --git a/infra/it/memory-benchmark-scripts/src/main/resources/memoryBenchmarkScript b/infra/it/memory-benchmark-scripts/src/main/resources/memoryBenchmarkScript new file mode 100644 index 000000000..120cb00e0 --- /dev/null +++ b/infra/it/memory-benchmark-scripts/src/main/resources/memoryBenchmarkScript @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +java -cp .:memory-benchmark-1.0.0-with-tests.jar ${testParams} org.junit.runner.JUnitCore ${testClass}
\ No newline at end of file diff --git a/infra/it/memory-benchmark/asciidoc/Readme.adoc b/infra/it/memory-benchmark/asciidoc/Readme.adoc new file mode 100644 index 000000000..80e2ffb6f --- /dev/null +++ b/infra/it/memory-benchmark/asciidoc/Readme.adoc @@ -0,0 +1,68 @@ += memory-benchmark + +Overview of memory-benchmark + += Tutorial += Configure + +To run honeycomb memory benchmark, use maven profile *memory-benchmark* like so + + mvn clean install -DskipTests -Pmemory-benchmark + +This will add following modules to build + +* _management_ - Enable JMX for honeycomb +* _memory-benchmark-scripts_ - Script generation for benchmarks +* _memory-benchmark-api_ - Test models for benchmark +* _memory-benchmark_ - Benchmark itself + +By default, 3 versions of run scripts are produces in project build folder + +* _honeycomb-memory-footprint-benchmark-0_ - Tests honeycomb memory footprint on rest without any config/context data +* _honeycomb-memory-footprint-benchmark-1000_ - Tests honeycomb memory footprint while 1000 data nodes present in config data +* _honeycomb-memory-footprint-benchmark-10000_ - Tests honeycomb memory footprint while 10000 data nodes present in config data + +Any other data sample size can be tested by modifying script parameter *-DsampleSize* + +== Run + +To run benchmark + + ./honeycomb-memory-footprint-benchmark-0 + +This will produce two output files. + +* memory-benchmark-on-rest-out-0-HeapMemoryUsage.csv +* memory-benchmark-on-rest-out-0-NonHeapMemoryUsage.csv + +For further explanation look at + + https://docs.oracle.com/javase/7/docs/api/java/lang/management/MemoryMXBean.html + + +Each of these files contains values in following format + + committed,init,max,used + 132644864,109051904,1525153792,12577144 + +These values stands for + + +* init - Represents the initial amount of memory (in bytes) that the Java virtual machine requests from the operating system for memory management during startup. +The Java virtual machine may request additional memory from the operating system and may also release memory to the system over time. +The value of init may be undefined(-1). +* used - Represents the amount of memory currently used (in bytes). +* committed - Represents the amount of memory (in bytes) that is guaranteed to be available for use by the Java virtual machine. +The amount of committed memory may change over time (increase or decrease). The Java virtual machine may release memory to the system and committed could be less than init. +Committed will always be greater than or equal to used. +* max - Represents the maximum amount of memory (in bytes) that can be used for memory management. Its value may be undefined(-1). + The maximum amount of memory may change over time if defined. + The amount of used and committed memory will always be less than or equal to max if max is defined. + A memory allocation may fail if it attempts to increase the used memory + such that used > committed even if used <= max would still be true (for example, when the system is low on virtual memory). + + + + + + diff --git a/infra/it/memory-benchmark/pom.xml b/infra/it/memory-benchmark/pom.xml new file mode 100644 index 000000000..8c93c0bef --- /dev/null +++ b/infra/it/memory-benchmark/pom.xml @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright (c) 2016 Cisco and/or its affiliates. + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at: + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <!-- Parent set as common script to use all groovy dependency versions, etc--> + <parent> + <groupId>io.fd.honeycomb.common</groupId> + <artifactId>honeycomb-parent</artifactId> + <version>1.17.04-SNAPSHOT</version> + <relativePath>../../../common/honeycomb-parent</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <groupId>io.fd.honeycomb.it</groupId> + <artifactId>memory-benchmark</artifactId> + <!-- Static version, we don't want it to be deployed anyway--> + <version>1.0.0</version> + <properties> + <commons-csv.version>1.4</commons-csv.version> + <honeycomb.version>1.17.04-SNAPSHOT</honeycomb.version> + <maven.groovy.version>2.0</maven.groovy.version> + <groovy.version>2.4.7</groovy.version> + <groovy.eclipse.compiler.version>2.9.2-01</groovy.eclipse.compiler.version> + <groovy.eclipse.batch.version>2.4.3-01</groovy.eclipse.batch.version> + </properties> + <!-- to be runnable from command line --> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>io.fd.honeycomb.it</groupId> + <artifactId>memory-benchmark-api</artifactId> + <version>${honeycomb.version}</version> + </dependency> + + <dependency> + <groupId>io.fd.honeycomb</groupId> + <artifactId>minimal-distribution</artifactId> + <version>${honeycomb.version}</version> + </dependency> + + <dependency> + <groupId>io.fd.honeycomb.it</groupId> + <artifactId>management</artifactId> + <version>${honeycomb.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-csv</artifactId> + <version>${commons-csv.version}</version> + </dependency> + + <dependency> + <groupId>org.codehaus.groovy</groupId> + <artifactId>groovy-all</artifactId> + <version>${groovy.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + + <!-- Skip deploy --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + + <!-- skips test by default but compile them --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.19.1</version> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> + + <!-- assemble jar with all dependencies and test classes --> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.3</version> + <configuration> + <descriptor>src/main/assembly/assembly.xml</descriptor> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- generate scripts for benchmarks --> + <plugin> + <groupId>org.codehaus.gmaven</groupId> + <artifactId>groovy-maven-plugin</artifactId> + <executions> + <!-- script for on-rest memory benchmark --> + <execution> + <id>generate-on-rest-benchmark-script</id> + <phase>package</phase> + <goals> + <goal>execute</goal> + </goals> + <!-- 0 data samples == empty config file, therefore same as honeycomb on rest --> + <configuration> + <source> + io.fd.honeycomb.benchmark.script.MemoryBenchmarkStartupScriptGenerator.generateWithDataScript(project, log, "memory-benchmark-on-rest-out", 0) + </source> + </configuration> + </execution> + <!-- script for memory benchmark with 1000 nodes in config data--> + <execution> + <id>generate-with-data-1000-benchmark-script</id> + <phase>package</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <source> + io.fd.honeycomb.benchmark.script.MemoryBenchmarkStartupScriptGenerator.generateWithDataScript(project, log, "memory-benchmark-with-data-out", 1000) + </source> + </configuration> + </execution> + <!-- script for memory benchmark with 10000 nodes in config data--> + <execution> + <id>generate-with-data-10000-benchmark-script</id> + <phase>package</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <source> + io.fd.honeycomb.benchmark.script.MemoryBenchmarkStartupScriptGenerator.generateWithDataScript(project, log, "memory-benchmark-with-data-out", 10000) + </source> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>io.fd.honeycomb.it</groupId> + <artifactId>benchmark-scripts</artifactId> + <version>1.17.04-SNAPSHOT</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> +</project>
\ No newline at end of file diff --git a/infra/it/memory-benchmark/src/main/assembly/assembly.xml b/infra/it/memory-benchmark/src/main/assembly/assembly.xml new file mode 100644 index 000000000..385d0dcb8 --- /dev/null +++ b/infra/it/memory-benchmark/src/main/assembly/assembly.xml @@ -0,0 +1,30 @@ +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> + <id>with-tests</id> + <formats> + <format>jar</format> + </formats> + <includeBaseDirectory>false</includeBaseDirectory> + <dependencySets> + <dependencySet> + <outputDirectory>/</outputDirectory> + <useProjectArtifact>true</useProjectArtifact> + <!-- Will include junit--> + <useProjectAttachments>true</useProjectAttachments> + <unpack>true</unpack> + <scope>test</scope> + </dependencySet> + </dependencySets> + <fileSets> + <fileSet> + <directory>${project.build.directory}/test-classes</directory> + <outputDirectory>/</outputDirectory> + <includes> + <include>**/*.class</include> + </includes> + <useDefaultExcludes>true</useDefaultExcludes> + </fileSet> + </fileSets> +</assembly>
\ No newline at end of file diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/BenchmarkFilesProvider.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/BenchmarkFilesProvider.java new file mode 100644 index 000000000..c7717d593 --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/BenchmarkFilesProvider.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.honeycomb.benchmark.memory; + + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.slf4j.Logger; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; +import java.util.function.Supplier; + +public interface BenchmarkFilesProvider { + + default void outputBenchmarkResult(@Nonnull final MemoryInfo benchmarkResult, + @Nonnull final String outputPath, + @Nonnull final Supplier<Logger> loggerSupplier) { + // specifies output file in form specified_name-memory_info_type.csv + final Path outPath = Paths.get(outputPath + "-" + benchmarkResult.getMemoryInfoTypeName() + ".csv"); + final CSVFormat csvFormat = CSVFormat.RFC4180.withHeader(MemoryInfo.COMMITTED, MemoryInfo.INIT, MemoryInfo.MAX, MemoryInfo.USED); + + try (final CSVPrinter csvPrinter = new CSVPrinter(new StringBuilder(), csvFormat)) { + // prints values in same order that header is + csvPrinter.printRecord(benchmarkResult.getCommitted(), benchmarkResult.getInit(), benchmarkResult.getMax(), benchmarkResult.getUsed()); + + loggerSupplier.get().info("Creating output file {}", outPath); + // writes output to separate file + Files.write(Files.createFile(outPath), Collections.singleton(csvPrinter.getOut().toString())); + } catch (IOException e) { + throw new IllegalStateException("Unable to output results of benchmark", e); + } + } + + + default String generateEmptyJsonFile(final String fileName) { + try { + Path tempFilePath = Files.createTempFile(fileName, ".json"); + + Files.write(tempFilePath, Arrays.asList("{}")); + + return tempFilePath.normalize().toString(); + } catch (IOException e) { + throw new IllegalStateException("Unable to create temp config data file"); + } + } + + /** + * Generate dummy data file to be provided for honeycomb as config data + */ + default String generateNonEmptyConfigDataFile(final String fileName, final int dataSampleSize) { + try { + Path tempFilePath = Files.createTempFile(fileName, ".json"); + + StringBuilder dataBuilder = new StringBuilder(); + + dataBuilder.append("{\"mm-bench:config-data\":{\"config-list\":["); + + for (int i = 0; i < dataSampleSize; i++) { + dataBuilder.append("{\"name\":\"") + .append(String.valueOf(i)) + .append("\"}"); + if (i != dataSampleSize - 1) { + dataBuilder.append(","); + } + } + + dataBuilder.append("]}}"); + + Files.write(tempFilePath, Arrays.asList(dataBuilder.toString())); + + return tempFilePath.normalize().toString(); + } catch (IOException e) { + throw new IllegalStateException("Unable to create temp config data file"); + } + } +} diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/MemoryFootprintBenchmark.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/MemoryFootprintBenchmark.java new file mode 100644 index 000000000..48d805975 --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/MemoryFootprintBenchmark.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.benchmark.memory; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Injector; +import com.google.inject.Module; +import io.fd.honeycomb.benchmark.memory.config.BindableCfgAttrsModule; +import io.fd.honeycomb.benchmark.memory.config.StaticHoneycombManagementModule; +import io.fd.honeycomb.benchmark.memory.write.NoopWritersModule; +import io.fd.honeycomb.infra.distro.Main; +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration; +import io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule; +import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule; +import io.fd.honeycomb.infra.distro.initializer.InitializerPipelineModule; +import io.fd.honeycomb.infra.distro.netconf.NetconfModule; +import io.fd.honeycomb.infra.distro.netconf.NetconfReadersModule; +import io.fd.honeycomb.infra.distro.restconf.RestconfModule; +import io.fd.honeycomb.infra.distro.schema.SchemaModule; +import io.fd.honeycomb.infra.distro.schema.YangBindingProviderModule; +import io.fd.honeycomb.management.jmx.JMXBeanProvider; +import org.eclipse.jetty.server.Server; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXServiceURL; +import java.util.Set; + +/** + * Measure memory consumption of config data storage + */ +public class MemoryFootprintBenchmark implements JMXBeanProvider, BenchmarkFilesProvider { + + private static final Logger LOG = LoggerFactory.getLogger(MemoryFootprintBenchmark.class); + + /** + * All modules from infra to load.Not static to not persist state + */ + private final Set<Module> BASE_MODULES = ImmutableSet.of( + new YangBindingProviderModule(), + new SchemaModule(), + new ConfigAndOperationalPipelineModule(), + new ContextPipelineModule(), + new InitializerPipelineModule(), + new NetconfModule(), + new NetconfReadersModule(), + new RestconfModule(), + // to enable jmx + new StaticHoneycombManagementModule(), + //adds noop writers + new NoopWritersModule()); + + // configuration class used to run benchmark, allows us to switch between honeycomb with data, or on rest + private final HoneycombConfiguration configuration; + + // output file path + private final String outputPath; + + public MemoryFootprintBenchmark(@Nonnull final HoneycombConfiguration configuration, @Nonnull final String outputPath) { + this.configuration = configuration; + this.outputPath = outputPath; + } + + public void run() throws Exception { + // start honeycomb with configuration of BASE_MODULES + configuration class + final Injector injector = startHoneycomb(); + + // query memory beans with JMX and output results on output path + queryMemoryBeans(injector.getInstance(JMXServiceURL.class)) + .forEach(memoryInfo -> outputBenchmarkResult(memoryInfo, outputPath, () -> LOG)); + // shutdowns server instance + injector.getInstance(Server.class).stop(); + } + + /** + * start honeycomb with basic modules + provided static configuration + */ + private Injector startHoneycomb() { + LOG.info("Starting embedded server with configuration {}", configuration); + return Main.init(ImmutableSet.<Module>builder() + .add(new BindableCfgAttrsModule(configuration)) + .addAll(BASE_MODULES).build()); + } + + /** + * Queries heap and non-heap memory usage + */ + private Set<MemoryInfo> queryMemoryBeans(final JMXServiceURL url) { + LOG.info("Requesting memory bean on url {}", url); + + try (final JMXConnector connector = getConnector(url)) { + MemoryInfo heapMemoryInfo = new MemoryInfo( + (CompositeDataSupport) getJMXAttribute(connector, MemoryInfo.MEMORY_MBEAN_TYPE, + MemoryInfo.HEAP_MEMORY), MemoryInfo.HEAP_MEMORY); + LOG.info("Heap memory usage {}", heapMemoryInfo); + + MemoryInfo nonHeapMemoryInfo = new MemoryInfo( + (CompositeDataSupport) getJMXAttribute(connector, MemoryInfo.MEMORY_MBEAN_TYPE, + MemoryInfo.NON_HEAP_MEMORY), MemoryInfo.NON_HEAP_MEMORY); + LOG.info("NonHeap memory usage {}", nonHeapMemoryInfo); + return ImmutableSet.of(heapMemoryInfo, nonHeapMemoryInfo); + } catch (Exception e) { + throw new IllegalStateException("Unable to query memory beans", e); + } + } + +} + diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/MemoryInfo.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/MemoryInfo.java new file mode 100644 index 000000000..f79006f78 --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/MemoryInfo.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.benchmark.memory; + +import javax.annotation.Nonnull; +import javax.management.openmbean.CompositeDataSupport; +import java.util.Arrays; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Wrapped from data extracted from JMX beans of type Memory + * */ +public final class MemoryInfo { + + public static final String MEMORY_MBEAN_TYPE = "java.lang:type=Memory"; + public static final String HEAP_MEMORY = "HeapMemoryUsage"; + public static final String NON_HEAP_MEMORY = "NonHeapMemoryUsage"; + + public static final String COMMITTED = "committed"; + public static final String INIT = "init"; + public static final String MAX = "max"; + public static final String USED = "used"; + + private final String memoryInfoTypeName; + private final long committed, init, max, used; + + public MemoryInfo(@Nonnull final CompositeDataSupport compositeData, @Nonnull final String memoryInfoTypeName) { + checkArgument(compositeData.getCompositeType().keySet().containsAll(Arrays.asList(COMMITTED, INIT, MAX, USED)), + "Submitted composite data %s does not contains necessary attributes", compositeData); + this.memoryInfoTypeName = memoryInfoTypeName; + this.committed = compositeDataAttributeValue(compositeData.get(COMMITTED)); + this.init = compositeDataAttributeValue(compositeData.get(INIT)); + this.max = compositeDataAttributeValue(compositeData.get(MAX)); + this.used = compositeDataAttributeValue(compositeData.get(USED)); + + } + + public String getMemoryInfoTypeName() { + return memoryInfoTypeName; + } + + public long getCommitted() { + return committed; + } + + public long getInit() { + return init; + } + + public long getMax() { + return max; + } + + public long getUsed() { + return used; + } + + @Override + public String toString() { + return memoryInfoTypeName + "[" + + "committed=" + committed + + ",init=" + init + + ",max=" + max + + ",used=" + used + + ']'; + } + + private static Long compositeDataAttributeValue(final Object commited) { + checkArgument(commited instanceof Long, "Unsupported memory attribute value %s", commited.getClass()); + return Long.class.cast(commited); + } +} diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/BindableCfgAttrsModule.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/BindableCfgAttrsModule.java new file mode 100644 index 000000000..03e3774db --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/BindableCfgAttrsModule.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.honeycomb.benchmark.memory.config; + + +import com.google.inject.AbstractModule; +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration; + +/** + * Provides ability to bind specific instance of static configuration + * */ +public class BindableCfgAttrsModule extends AbstractModule { + + private final HoneycombConfiguration configToBind; + + public BindableCfgAttrsModule(HoneycombConfiguration configToBind) { + this.configToBind = configToBind; + } + + @Override + protected void configure() { + // Inject non-dependency configuration + bind(HoneycombConfiguration.class).toInstance(configToBind); + } +} diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/StaticHoneycombConfiguration.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/StaticHoneycombConfiguration.java new file mode 100644 index 000000000..6bcf7ef68 --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/StaticHoneycombConfiguration.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.honeycomb.benchmark.memory.config; + +import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration; + +import javax.annotation.Nonnull; +import java.io.Closeable; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Optional; + +/** + * Static configuration to prevent injecting of properties from json fles + */ +public class StaticHoneycombConfiguration extends HoneycombConfiguration implements Closeable { + + public StaticHoneycombConfiguration(@Nonnull final String persistConfigPath, @Nonnull final String persistContextPath) { + this.peristConfigPath = persistConfigPath; + this.peristContextPath = persistContextPath; + + this.username = "admin"; + this.password = "admin"; + this.notificationServiceQueueDepth = 1; + this.restconfBindingAddress = Optional.of("/restconf"); + this.restconfPort = Optional.of(8187); + this.restconfBindingAddress = Optional.of("127.0.0.1"); + this.persistedConfigRestorationType = "Merge"; + this.persistedContextRestorationType = "Merge"; + this.restconfWebsocketPort = Optional.of(7890); + } + + @Override + public boolean isConfigPersistenceEnabled() { + return false; + } + + @Override + public boolean isRestconfHttpsEnabled() { + return false; + } + + @Override + public boolean isRestconfHttpEnabled() { + return true; + } + + @Override + public boolean isRestconfEnabled() { + return true; + } + + @Override + public boolean isNetconfTcpEnabled() { + return false; + } + + @Override + public boolean isContextPersistenceEnabled() { + return false; + } + + @Override + public boolean isNetconfEnabled() { + return false; + } + + @Override + public boolean isNetconfSshEnabled() { + return false; + } + + @Override + public void close() throws IOException { + if (Files.exists(Paths.get(peristConfigPath))) { + Files.delete(Paths.get(peristConfigPath)); + } + + if (Files.exists(Paths.get(peristContextPath))) { + Files.delete(Paths.get(peristContextPath)); + } + } +} diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/StaticHoneycombManagementModule.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/StaticHoneycombManagementModule.java new file mode 100644 index 000000000..a91d6ba84 --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/config/StaticHoneycombManagementModule.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.honeycomb.benchmark.memory.config; + +import io.fd.honeycomb.management.jmx.ConnectorServerProvider; +import io.fd.honeycomb.management.jmx.HoneycombManagementConfig; +import io.fd.honeycomb.management.jmx.HoneycombManagementModule; +import io.fd.honeycomb.management.jmx.JMXServiceUrlProvider; +import org.eclipse.jetty.jmx.ConnectorServer; +import org.eclipse.jetty.jmx.MBeanContainer; + +import javax.management.remote.JMXServiceURL; +import java.lang.management.ManagementFactory; + +/** + * In this case we need to override Honeycomb config, but if standard management module is active, + * configuration module injection will cause attempt to inject attributes in HoneycombConfiguration, + * even if static instance is provider. Therefore here we need to override configure to also provide + * static instance for HoneycombManagementConfig + */ +public class StaticHoneycombManagementModule extends HoneycombManagementModule { + + @Override + protected void configure() { + // all values are wrapped in Optionals with default values + bind(HoneycombManagementConfig.class).toInstance(new HoneycombManagementConfig()); + bind(MBeanContainer.class).toInstance(new MBeanContainer(ManagementFactory.getPlatformMBeanServer())); + bind(JMXServiceURL.class).toProvider(JMXServiceUrlProvider.class); + bind(ConnectorServer.class).toProvider(ConnectorServerProvider.class).asEagerSingleton(); + + showAvailableBeans(); + } +} diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/write/NoopWriter.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/write/NoopWriter.java new file mode 100644 index 000000000..000a176df --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/write/NoopWriter.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.honeycomb.benchmark.memory.write; + +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.translate.write.Writer; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public final class NoopWriter<T extends DataObject> implements Writer<T> { + + private final InstanceIdentifier<T> id; + + public NoopWriter(final InstanceIdentifier<T> id) { + this.id = id; + } + + @Override + public void update(@Nonnull final InstanceIdentifier<? extends DataObject> id, + @Nullable final DataObject dataBefore, + @Nullable final DataObject dataAfter, + @Nonnull final WriteContext ctx) throws WriteFailedException { + // NOOP + } + + @Nonnull + @Override + public InstanceIdentifier<T> getManagedDataObjectType() { + return id; + } + + @Override + public String toString() { + return "NoopWriter{" + + id.getTargetType().getSimpleName() + '}'; + } +}
\ No newline at end of file diff --git a/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/write/NoopWritersModule.java b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/write/NoopWritersModule.java new file mode 100644 index 000000000..a88c514c4 --- /dev/null +++ b/infra/it/memory-benchmark/src/main/java/io/fd/honeycomb/benchmark/memory/write/NoopWritersModule.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.honeycomb.benchmark.memory.write; + +import com.google.inject.AbstractModule; +import com.google.inject.multibindings.Multibinder; +import io.fd.honeycomb.translate.write.WriterFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.memory.benchmark.rev161204.ConfigData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.memory.benchmark.rev161204.config.data.ConfigList; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class NoopWritersModule extends AbstractModule { + @Override + protected void configure() { + + final Multibinder<WriterFactory> writeBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); + writeBinder.addBinding().toInstance(registry -> { + // Add noop writers for all data written in this benchmark + + registry.add(new NoopWriter<>(InstanceIdentifier.create(ConfigData.class))); + registry.add(new NoopWriter<>(InstanceIdentifier.create(ConfigData.class).child(ConfigList.class))); + }); + } + +} diff --git a/infra/it/memory-benchmark/src/test/java/io/fd/honeycomb/benchmark/memory/HoneycombFootprintTest.java b/infra/it/memory-benchmark/src/test/java/io/fd/honeycomb/benchmark/memory/HoneycombFootprintTest.java new file mode 100644 index 000000000..b8817f8f4 --- /dev/null +++ b/infra/it/memory-benchmark/src/test/java/io/fd/honeycomb/benchmark/memory/HoneycombFootprintTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fd.honeycomb.benchmark.memory; + +import io.fd.honeycomb.benchmark.memory.config.StaticHoneycombConfiguration; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Objects; + +/** + * Test honeycomb memory footprint while containing amount of nodes specified by + * parameter sampleSize.<br> + * Test must be triggered by separated scripts, not by Parametrized runner,<br> + * because of classes like WebSocketServer that is internally a singleton, therefore it holds static reference<br> + * on itself and would fail on second run on precondition, because junit kills threads, but does not unload classes + */ +public class HoneycombFootprintTest implements BenchmarkFilesProvider { + + private static final String SAMPLE_SIZE_PROP = "sampleSize"; + private static final String OUTPUT_PROP = "outPath"; + + private StaticHoneycombConfiguration staticHoneycombConfiguration; + private String outputPath; + + @Before + public void init() { + outputPath = Objects.requireNonNull(System.getProperty(OUTPUT_PROP), + "No output file path specified, make sure you've specified -D" + OUTPUT_PROP + " parameter"); + } + + @Test + public void testHoneycombMemoryFootprintWithData() throws Exception { + final int dataSampleSize = Integer.valueOf(Objects.requireNonNull(System.getProperty(SAMPLE_SIZE_PROP), + "No sample data size defined, make sure you've specified -D" + SAMPLE_SIZE_PROP + " parameter")); + + staticHoneycombConfiguration = new StaticHoneycombConfiguration( + generateNonEmptyConfigDataFile("temp-config", dataSampleSize), + generateEmptyJsonFile("temp-empty-context")); + + new MemoryFootprintBenchmark(staticHoneycombConfiguration, outputPath).run(); + } + + @After + public void destroyTest() throws IOException { + // removes temp files,etc + staticHoneycombConfiguration.close(); + } +} diff --git a/infra/it/pom.xml b/infra/it/pom.xml index da6e3c2b8..cbf8eae62 100644 --- a/infra/it/pom.xml +++ b/infra/it/pom.xml @@ -34,15 +34,33 @@ <module>it-test</module> </modules> - - <!-- Activate from command line with mvn <goals> -Pbenchmark --> <profiles> + <!-- Activate from command line with mvn <goals> -Pbenchmark --> <profile> <id>benchmark</id> <modules> <module>benchmark</module> </modules> </profile> + + <!-- Activate management module --> + <profile> + <id>management</id> + <modules> + <module>management</module> + </modules> + </profile> + + <!-- Activate memory benchmarking modules --> + <profile> + <id>memory-benchmark</id> + <modules> + <module>management</module> + <module>memory-benchmark-scripts</module> + <module>memory-benchmark</module> + <module>memory-benchmark-api</module> + </modules> + </profile> </profiles> <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build --> |