From 1000f0bd9ff8ed6f5063845a525914c531342838 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 19 Oct 2016 10:16:31 -0700 Subject: [PATCH] Adding a geode-benchmark project with support for running jmh benchmarks Adding a new project with a couple of simple benchmarks using jmh, to make it easier for developers to write microbenchmarks of geode. --- build.gradle | 1 + geode-benchmarks/build.gradle | 26 +++++ .../RangeQueryWithIndexBenchmark.java | 104 ++++++++++++++++++ .../benchmark/RegionOperationBenchmark.java | 62 +++++++++++ settings.gradle | 1 + 5 files changed, 194 insertions(+) create mode 100644 geode-benchmarks/build.gradle create mode 100644 geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RangeQueryWithIndexBenchmark.java create mode 100644 geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RegionOperationBenchmark.java diff --git a/build.gradle b/build.gradle index 6e82433e81ad..360310fbd58b 100755 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ buildscript { classpath 'com.bmuschko:gradle-nexus-plugin:2.3.1' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.0.1' classpath "com.diffplug.gradle.spotless:spotless:2.2.0" + classpath "me.champeau.gradle:jmh-gradle-plugin:0.3.1" } } diff --git a/geode-benchmarks/build.gradle b/geode-benchmarks/build.gradle new file mode 100644 index 000000000000..b6f09bcff645 --- /dev/null +++ b/geode-benchmarks/build.gradle @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +apply plugin: "me.champeau.gradle.jmh" + +dependencies { + compile project(':geode-core') +} + +jmh { + duplicateClassesStrategy = 'warn' +} diff --git a/geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RangeQueryWithIndexBenchmark.java b/geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RangeQueryWithIndexBenchmark.java new file mode 100644 index 000000000000..7255c1a98a75 --- /dev/null +++ b/geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RangeQueryWithIndexBenchmark.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.cache.benchmark; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import java.util.stream.IntStream; + +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.CacheFactory; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache.query.FunctionDomainException; +import org.apache.geode.cache.query.IndexExistsException; +import org.apache.geode.cache.query.IndexNameConflictException; +import org.apache.geode.cache.query.NameResolutionException; +import org.apache.geode.cache.query.Query; +import org.apache.geode.cache.query.QueryInvocationTargetException; +import org.apache.geode.cache.query.RegionNotFoundException; +import org.apache.geode.cache.query.SelectResults; +import org.apache.geode.cache.query.TypeMismatchException; +import org.apache.geode.cache.query.internal.index.AbstractIndex; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +@Fork(3) +public class RangeQueryWithIndexBenchmark { + + @State(Scope.Benchmark) + public static class CacheState { + private Region region; + private Query query; + + public CacheState() {} + + @Setup + public void setup() { + Cache cache = new CacheFactory().set("mcast-port", "0").set("locators", "").create(); + + region = cache.createRegionFactory(RegionShortcut.REPLICATE).create("region"); + try { + AbstractIndex index = + (AbstractIndex) cache.getQueryService().createIndex("Status", "id", "/region"); + + IntStream.range(0, 10000).forEach(i -> region.put(i, new Value(i))); + query = cache.getQueryService().newQuery("select * from /region where id > 0"); + + // Do the query once to make sure it's actually returning results + // And using the index + SelectResults results = query(); + assertEquals(9999, results.size()); + assertEquals(1, index.getStatistics().getTotalUses()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + public SelectResults query() throws NameResolutionException, TypeMismatchException, + QueryInvocationTargetException, FunctionDomainException { + return (SelectResults) query.execute(); + } + } + + @Benchmark + @Warmup(iterations = 20) + @Measurement(iterations = 20) + public Object query(CacheState state) throws NameResolutionException, TypeMismatchException, + QueryInvocationTargetException, FunctionDomainException { + return state.query(); + } + + + + public static class Value { + protected final int id; + + public Value(int id) { + this.id = id; + } + + public int getId() { + return id; + } + } +} diff --git a/geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RegionOperationBenchmark.java b/geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RegionOperationBenchmark.java new file mode 100644 index 000000000000..1dc0e643b430 --- /dev/null +++ b/geode-benchmarks/src/jmh/java/org/apache/geode/cache/benchmark/RegionOperationBenchmark.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.cache.benchmark; + +import static org.junit.Assert.*; + +import java.util.stream.IntStream; + +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.CacheFactory; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache.query.FunctionDomainException; +import org.apache.geode.cache.query.NameResolutionException; +import org.apache.geode.cache.query.Query; +import org.apache.geode.cache.query.QueryInvocationTargetException; +import org.apache.geode.cache.query.SelectResults; +import org.apache.geode.cache.query.TypeMismatchException; +import org.apache.geode.cache.query.internal.index.AbstractIndex; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +@Fork(10) +public class RegionOperationBenchmark { + + @State(Scope.Benchmark) + public static class CacheState { + private Region region; + + @Setup + public void setup() { + Cache cache = new CacheFactory().set("mcast-port", "0").set("locators", "").create(); + + region = cache.createRegionFactory(RegionShortcut.REPLICATE).create("region"); + } + } + + @Benchmark + @Warmup(iterations = 20) + @Measurement(iterations = 20) + public Object put(CacheState state) throws NameResolutionException, TypeMismatchException, + QueryInvocationTargetException, FunctionDomainException { + return state.region.put("key", "value"); + } +} diff --git a/settings.gradle b/settings.gradle index 5aaa17ad69d1..8e2673a7750f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,6 +29,7 @@ include 'geode-lucene' include 'geode-old-client-support' include 'geode-wan' include 'geode-cq' +include 'geode-benchmarks' include 'extensions/geode-modules' include 'extensions/geode-modules-tomcat7' include 'extensions/geode-modules-tomcat8'