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);
+    }
+}

Reply via email to