You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by ij...@apache.org on 2017/03/06 11:56:30 UTC
kafka git commit: KAFKA-3989;
Initial support for adding a JMH benchmarking module
Repository: kafka
Updated Branches:
refs/heads/trunk f111f2a71 -> 79f85039d
KAFKA-3989; Initial support for adding a JMH benchmarking module
Author: bbejeck <bb...@gmail.com>
Reviewers: Ewen Cheslack-Postava <ew...@confluent.io>, Ismael Juma <is...@juma.me.uk>
Closes #1712 from bbejeck/KAFKA-3989_create_jmh_benchmarking_module
Project: http://git-wip-us.apache.org/repos/asf/kafka/repo
Commit: http://git-wip-us.apache.org/repos/asf/kafka/commit/79f85039
Tree: http://git-wip-us.apache.org/repos/asf/kafka/tree/79f85039
Diff: http://git-wip-us.apache.org/repos/asf/kafka/diff/79f85039
Branch: refs/heads/trunk
Commit: 79f85039d7be1b4266f06715a487f3635558ded6
Parents: f111f2a
Author: bbejeck <bb...@gmail.com>
Authored: Mon Mar 6 10:47:36 2017 +0000
Committer: Ismael Juma <is...@juma.me.uk>
Committed: Mon Mar 6 11:56:14 2017 +0000
----------------------------------------------------------------------
build.gradle | 43 +++++++++++++
checkstyle/import-control.xml | 9 +++
jmh-benchmarks/README.md | 61 ++++++++++++++++++
jmh-benchmarks/jmh.sh | 42 ++++++++++++
.../kafka/jmh/cache/LRUCacheBenchmark.java | 68 ++++++++++++++++++++
settings.gradle | 2 +-
6 files changed, 224 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/kafka/blob/79f85039/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index caac99d..57beebe 100644
--- a/build.gradle
+++ b/build.gradle
@@ -27,6 +27,7 @@ buildscript {
classpath "org.ajoberstar:grgit:1.7.0"
classpath 'com.github.ben-manes:gradle-versions-plugin:0.13.0'
classpath 'org.scoverage:gradle-scoverage:2.1.0'
+ classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4'
}
}
@@ -822,6 +823,48 @@ project(':streams:examples') {
}
}
+project(':jmh-benchmarks') {
+
+ apply plugin: 'com.github.johnrengelman.shadow'
+
+ shadowJar {
+ baseName = 'kafka-jmh-benchmarks-all'
+ classifier = null
+ version = null
+ }
+
+ dependencies {
+ compile project(':clients')
+ compile project(':streams')
+ compile 'org.openjdk.jmh:jmh-core:1.17.5'
+ compile 'org.openjdk.jmh:jmh-generator-annprocess:1.17.5'
+ compile 'org.openjdk.jmh:jmh-core-benchmarks:1.17.5'
+ }
+
+ jar {
+ manifest {
+ attributes "Main-Class": "org.openjdk.jmh.Main"
+ }
+ }
+
+
+ task jmh(type: JavaExec, dependsOn: [':jmh-benchmarks:clean', ':jmh-benchmarks:shadowJar']) {
+
+ main="-jar"
+
+ doFirst {
+ if (System.getProperty("jmhArgs")) {
+ args System.getProperty("jmhArgs").split(',')
+ }
+ args = [shadowJar.archivePath, *args]
+ }
+ }
+
+ javadoc {
+ enabled = false
+ }
+}
+
project(':log4j-appender') {
archivesBaseName = "kafka-log4j-appender"
http://git-wip-us.apache.org/repos/asf/kafka/blob/79f85039/checkstyle/import-control.xml
----------------------------------------------------------------------
diff --git a/checkstyle/import-control.xml b/checkstyle/import-control.xml
index 6c72e63..fa98593 100644
--- a/checkstyle/import-control.xml
+++ b/checkstyle/import-control.xml
@@ -181,6 +181,15 @@
</subpackage>
</subpackage>
+ <subpackage name="jmh">
+ <allow pkg="org.openjdk.jmh.annotations" />
+ <allow pkg="org.openjdk.jmh.runner" />
+ <allow pkg="org.openjdk.jmh.runner.options" />
+ <allow pkg="org.apache.kafka.common" />
+ <allow pkg="org.apache.kafka.streams" />
+ <allow pkg="org.github.jamm" />
+ </subpackage>
+
<subpackage name="log4jappender">
<allow pkg="org.apache.log4j" />
<allow pkg="org.apache.kafka.clients" />
http://git-wip-us.apache.org/repos/asf/kafka/blob/79f85039/jmh-benchmarks/README.md
----------------------------------------------------------------------
diff --git a/jmh-benchmarks/README.md b/jmh-benchmarks/README.md
new file mode 100644
index 0000000..53807ea
--- /dev/null
+++ b/jmh-benchmarks/README.md
@@ -0,0 +1,61 @@
+###JMH-Benchmark module
+
+This module contains benchmarks written using [JMH](http://openjdk.java.net/projects/code-tools/jmh/) from OpenJDK.
+Writing correct micro-benchmarks is Java (or another JVM language) is difficult and there are many non-obvious pitfalls (many
+due to compiler optimizations). JMH is a framework for running and analyzing benchmarks (micro or macro) written in Java (or
+another JVM language).
+
+For help in writing correct JMH tests, the best place to start is the [sample code](http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/) provided
+by the JMH project.
+
+Typically, JMH is expected to run as a separate project in Maven. The jmh-benchmarks module uses
+the [gradle shadow jar](https://github.com/johnrengelman/shadow) plugin to emulate this behavior, by creating the required
+uber-jar file containing the benchmarking code and required JMH classes.
+
+JMH is highly configurable and users are encouraged to look through the samples for suggestions
+on what options are available. A good tutorial for using JMH can be found [here](http://tutorials.jenkov.com/java-performance/jmh.html#return-value-from-benchmark-method)
+
+###Gradle Tasks / Running benchmarks in gradle
+
+If no benchmark mode is specified, the default is used which is throughput. It is assumed that users run
+the gradle tasks with './gradlew' from the root of the Kafka project.
+
+* jmh-benchmarks:shadowJar - creates the uber jar required to run the benchmarks.
+
+* jmh-benchmarks:jmh - runs the `clean` and `shadowJar` tasks followed by all the benchmarks.
+
+### Using the jmh script
+If you want to set specific JMH flags or only run a certain test(s) passing arguments via
+gradle tasks is cumbersome. Instead you can use the `jhm.sh` script. NOTE: It is assumed users run
+the jmh.sh script from the jmh-benchmarks module.
+
+* Run a specific test setting fork-mode (number iterations) to 2 :`./jmh.sh -f 2 LRUCacheBenchmark`
+
+* By default all JMH output goes to stdout. To run a benchmark and capture the results in a file:
+`./jmh.sh -f 2 -o benchmarkResults.txt LRUCacheBenchmark`
+NOTE: For now this script needs to be run from the jmh-benchmarks directory.
+
+### Running JMH outside of gradle
+The JMH benchmarks can be run outside of gradle as you would with any executable jar file:
+`java -jar <kafka-repo-dir>/jmh-benchmarks/build/libs/kafka-jmh-benchmarks-all.jar -f2 LRUCacheBenchmark`
+
+### JMH Options
+Some common JMH options are:
+```text
+
+ -e <regexp+> Benchmarks to exclude from the run.
+
+ -f <int> How many times to fork a single benchmark. Use 0 to
+ disable forking altogether. Warning: disabling
+ forking may have detrimental impact on benchmark
+ and infrastructure reliability, you might want
+ to use different warmup mode instead.
+
+ -o <filename> Redirect human-readable output to a given file.
+
+
+
+ -v <mode> Verbosity mode. Available modes are: [SILENT, NORMAL,
+ EXTRA]
+```
+To view all options run jmh with the -h flag.
http://git-wip-us.apache.org/repos/asf/kafka/blob/79f85039/jmh-benchmarks/jmh.sh
----------------------------------------------------------------------
diff --git a/jmh-benchmarks/jmh.sh b/jmh-benchmarks/jmh.sh
new file mode 100755
index 0000000..7f3927a
--- /dev/null
+++ b/jmh-benchmarks/jmh.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+# 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.
+
+base_dir=$(dirname $0)
+jmh_project_name="jmh-benchmarks"
+
+if [ ${base_dir} == "." ]; then
+ gradlew_dir=".."
+elif [ ${base_dir} == ${jmh_project_name} ]; then
+ gradlew_dir="."
+else
+ echo "JMH Benchmarks need to be run from the root of the kafka repository or the 'jmh-benchmarks' directory"
+ exit
+fi
+
+gradleCmd="${gradlew_dir}/gradlew"
+libDir="${base_dir}/build/libs"
+
+echo "running gradlew :jmh-benchmarks:clean :jmh-benchmarks:shadowJar in quiet mode"
+
+$gradleCmd -q :jmh-benchmarks:clean :jmh-benchmarks:shadowJar
+
+echo "gradle build done"
+
+echo "running JMH with args [$@]"
+
+java -jar ${libDir}/kafka-jmh-benchmarks-all.jar "$@"
+
+echo "JMH benchmarks done"
http://git-wip-us.apache.org/repos/asf/kafka/blob/79f85039/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/cache/LRUCacheBenchmark.java
----------------------------------------------------------------------
diff --git a/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/cache/LRUCacheBenchmark.java b/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/cache/LRUCacheBenchmark.java
new file mode 100644
index 0000000..ecf73f9
--- /dev/null
+++ b/jmh-benchmarks/src/main/java/org/apache/kafka/jmh/cache/LRUCacheBenchmark.java
@@ -0,0 +1,68 @@
+/*
+ * 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.kafka.jmh.cache;
+
+import org.apache.kafka.common.cache.LRUCache;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * This is a simple example of a JMH benchmark.
+ *
+ * The sample code provided by the JMH project is a great place to start learning how to write correct benchmarks:
+ * http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/
+ */
+@State(Scope.Thread)
+public class LRUCacheBenchmark {
+
+ private LRUCache<String, String> lruCache;
+
+ private final String key = "the_key_to_use";
+ private final String value = "the quick brown fox jumped over the lazy dog the olympics are about to start";
+ int counter;
+
+
+ @Setup(Level.Trial)
+ public void setUpCaches() {
+ lruCache = new LRUCache<>(100);
+ }
+
+ @Benchmark
+ public String testCachePerformance() {
+ counter++;
+ lruCache.put(key + counter, value + counter);
+ return lruCache.get(key + counter);
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(LRUCacheBenchmark.class.getSimpleName())
+ .forks(2)
+ .build();
+
+ new Runner(opt).run();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/kafka/blob/79f85039/settings.gradle
----------------------------------------------------------------------
diff --git a/settings.gradle b/settings.gradle
index 29d3895..f0fdf07 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -14,4 +14,4 @@
// limitations under the License.
include 'core', 'examples', 'clients', 'tools', 'streams', 'streams:examples', 'log4j-appender',
- 'connect:api', 'connect:transforms', 'connect:runtime', 'connect:json', 'connect:file'
+ 'connect:api', 'connect:transforms', 'connect:runtime', 'connect:json', 'connect:file', 'jmh-benchmarks'