Repository: cassandra Updated Branches: refs/heads/trunk fd63d2ae2 -> c23560347
Integrate JMH into build system patch by tjake; reviewed by Jason Brown for CASSANDRA-8151 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c2356034 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c2356034 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c2356034 Branch: refs/heads/trunk Commit: c235603475358e458c6ce9fed983b68e604d5e25 Parents: fd63d2a Author: T Jake Luciani <[email protected]> Authored: Tue Oct 21 09:57:12 2014 -0400 Committer: T Jake Luciani <[email protected]> Committed: Tue Oct 21 09:57:12 2014 -0400 ---------------------------------------------------------------------- CHANGES.txt | 1 + build.xml | 26 ++++ .../cassandra/test/microbench/Sample.java | 130 +++++++++++++++++++ 3 files changed, 157 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2356034/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index c1d262d..85cb24b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0 + * Integrate JMH for microbenchmarks (CASSANDRA-8151) * Keep sstable levels when bootstrapping (CASSANDRA-7460) * Add Sigar library and perform basic OS settings check on startup (CASSANDRA-7838) * Support for aggregation functions (CASSANDRA-4914) http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2356034/build.xml ---------------------------------------------------------------------- diff --git a/build.xml b/build.xml index 07d0578..9cd80c2 100644 --- a/build.xml +++ b/build.xml @@ -56,10 +56,12 @@ <property name="test.conf" value="${test.dir}/conf"/> <property name="test.data" value="${test.dir}/data"/> <property name="test.name" value="*Test"/> + <property name="benchmark.name" value=""/> <property name="test.methods" value=""/> <property name="test.runners" value="1"/> <property name="test.unit.src" value="${test.dir}/unit"/> <property name="test.long.src" value="${test.dir}/long"/> + <property name="test.microbench.src" value="${test.dir}/microbench"/> <property name="test.pig.src" value="${test.dir}/pig"/> <property name="dist.dir" value="${build.dir}/dist"/> @@ -356,6 +358,9 @@ <dependency groupId="org.jacoco" artifactId="org.jacoco.agent" version="${jacoco.version}"/> <dependency groupId="org.jacoco" artifactId="org.jacoco.ant" version="${jacoco.version}"/> + <dependency groupId="org.openjdk.jmh" artifactId="jmh-core" version="1.1.1"/> + <dependency groupId="org.openjdk.jmh" artifactId="jmh-generator-annprocess" version="1.1.1"/> + <dependency groupId="org.apache.cassandra" artifactId="cassandra-all" version="${version}" /> <dependency groupId="org.apache.cassandra" artifactId="cassandra-thrift" version="${version}" /> <dependency groupId="com.yammer.metrics" artifactId="metrics-core" version="2.2.0" /> @@ -415,6 +420,8 @@ <dependency groupId="com.datastax.cassandra" artifactId="cassandra-driver-core"/> <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations"/> <dependency groupId="org.javassist" artifactId="javassist"/> + <dependency groupId="org.openjdk.jmh" artifactId="jmh-core"/> + <dependency groupId="org.openjdk.jmh" artifactId="jmh-generator-annprocess"/> </artifact:pom> <artifact:pom id="coverage-deps-pom" @@ -1062,6 +1069,7 @@ <src path="${test.unit.src}"/> <src path="${test.long.src}"/> <src path="${test.pig.src}"/> + <src path="${test.microbench.src}"/> </javac> <!-- Non-java resources needed by the test suite --> @@ -1510,6 +1518,24 @@ ]]> </script> </target> + <!-- run microbenchmarks suite --> + <target name="microbench" depends="build-test"> + <java classname="org.openjdk.jmh.Main" + fork="true" + failonerror="true"> + <classpath> + <path refid="cassandra.classpath" /> + <pathelement location="${test.classes}"/> + <path refid="cobertura.classpath"/> + <pathelement location="${test.conf}"/> + <fileset dir="${test.lib}"> + <include name="**/*.jar" /> + </fileset> + </classpath> + <arg value=".*microbench.*${benchmark.name}"/> + </java> + </target> + <!-- Generate Eclipse project description files --> <target name="generate-eclipse-files" depends="build" description="Generate eclipse files"> <echo file=".project"><![CDATA[<?xml version="1.0" encoding="UTF-8"?> http://git-wip-us.apache.org/repos/asf/cassandra/blob/c2356034/test/microbench/org/apache/cassandra/test/microbench/Sample.java ---------------------------------------------------------------------- diff --git a/test/microbench/org/apache/cassandra/test/microbench/Sample.java b/test/microbench/org/apache/cassandra/test/microbench/Sample.java new file mode 100644 index 0000000..1f149c0 --- /dev/null +++ b/test/microbench/org/apache/cassandra/test/microbench/Sample.java @@ -0,0 +1,130 @@ +/** + * 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.cassandra.test.microbench; + +import net.jpountz.lz4.LZ4Compressor; +import net.jpountz.lz4.LZ4Factory; +import net.jpountz.lz4.LZ4FastDecompressor; +import org.openjdk.jmh.annotations.*; +import org.xerial.snappy.Snappy; + +import java.io.IOException; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) +@Fork(value = 1,jvmArgsAppend = "-Xmx512M") +@Threads(1) +@State(Scope.Benchmark) +public class Sample +{ + @Param({"65536"}) + private int pageSize; + + @Param({"1024"}) + private int uniquePages; + + @Param({"0.1"}) + private double randomRatio; + + @Param({"4..16"}) + private String randomRunLength; + + @Param({"4..128"}) + private String duplicateLookback; + + private byte[][] lz4Bytes; + private byte[][] snappyBytes; + private byte[][] rawBytes; + + private LZ4FastDecompressor lz4Decompressor = LZ4Factory.fastestInstance().fastDecompressor(); + + private LZ4Compressor lz4Compressor = LZ4Factory.fastestInstance().fastCompressor(); + + @State(Scope.Thread) + public static class ThreadState + { + byte[] bytes; + } + + @Setup + public void setup() throws IOException + { + ThreadLocalRandom random = ThreadLocalRandom.current(); + int[] randomRunLength = range(this.randomRunLength); + int[] duplicateLookback = range(this.duplicateLookback); + rawBytes = new byte[uniquePages][pageSize]; + lz4Bytes = new byte[uniquePages][]; + snappyBytes = new byte[uniquePages][]; + byte[][] runs = new byte[duplicateLookback[1] - duplicateLookback[0]][]; + for (int i = 0 ; i < rawBytes.length ; i++) + { + byte[] trg = rawBytes[0]; + int runCount = 0; + int byteCount = 0; + while (byteCount < trg.length) + { + byte[] nextRun; + if (runCount == 0 || random.nextDouble() < this.randomRatio) + { + nextRun = new byte[random.nextInt(randomRunLength[0], randomRunLength[1])]; + random.nextBytes(nextRun ); + runs[runCount % runs.length] = nextRun; + runCount++; + } + else + { + int index = runCount < duplicateLookback[1] + ? random.nextInt(runCount) + : (runCount - random.nextInt(duplicateLookback[0], duplicateLookback[1])); + nextRun = runs[index % runs.length]; + } + System.arraycopy(nextRun, 0, trg, byteCount, Math.min(nextRun.length, trg.length - byteCount)); + byteCount += nextRun.length; + } + lz4Bytes[i] = lz4Compressor.compress(trg); + snappyBytes[i] = Snappy.compress(trg); + } + } + + static int[] range(String spec) + { + String[] split = spec.split("\\.\\."); + return new int[] { Integer.parseInt(split[0]), Integer.parseInt(split[1]) }; + } + + @Benchmark + public void lz4(ThreadState state) + { + if (state.bytes == null) + state.bytes = new byte[this.pageSize]; + byte[] in = lz4Bytes[ThreadLocalRandom.current().nextInt(lz4Bytes.length)]; + lz4Decompressor.decompress(in, state.bytes); + } + + @Benchmark + public void snappy(ThreadState state) throws IOException + { + byte[] in = snappyBytes[ThreadLocalRandom.current().nextInt(snappyBytes.length)]; + state.bytes = Snappy.uncompress(in); + } +}
