You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by wi...@apache.org on 2018/11/20 19:02:54 UTC

[geode-benchmarks] branch develop updated: Adding new class to evaluate a test run against a baseline

This is an automated email from the ASF dual-hosted git repository.

wirebaron pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode-benchmarks.git


The following commit(s) were added to refs/heads/develop by this push:
     new 178ad74  Adding new class to evaluate a test run against a baseline
178ad74 is described below

commit 178ad74147914224ce8d61c7d9282a50908e1721
Author: Brian Rowe <br...@pivotal.io>
AuthorDate: Tue Nov 20 11:02:50 2018 -0800

    Adding new class to evaluate a test run against a baseline
    
    Adding new class to evaluate a test run against a baseline and output the relative performance.
---
 .../perftest/analysis/BenchmarkRunAnalyzer.java    | 102 +++++++++++++++
 .../geode/perftest/analysis/ProbeResultParser.java |  34 +++++
 .../YardstickPercentileSensorParser.java           |  43 +++++--
 .../YardstickThroughputSensorParser.java           |  70 +++++++----
 .../analysis/BenchmarkRunAnalyzerTest.java         | 139 +++++++++++++++++++++
 .../YardstickPercentileSensorParserTest.java       |   4 +-
 .../YardstickThroughputSensorParserTest.java       |   4 +-
 7 files changed, 362 insertions(+), 34 deletions(-)

diff --git a/harness/src/main/java/org/apache/geode/perftest/analysis/BenchmarkRunAnalyzer.java b/harness/src/main/java/org/apache/geode/perftest/analysis/BenchmarkRunAnalyzer.java
new file mode 100644
index 0000000..c095876
--- /dev/null
+++ b/harness/src/main/java/org/apache/geode/perftest/analysis/BenchmarkRunAnalyzer.java
@@ -0,0 +1,102 @@
+/*
+ * 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.perftest.analysis;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Analyzer that takes in benchmarks, probes, and result directories and produces
+ * a comparison of the results to a provided writer.
+ *
+ * This currently handles data in the format
+ * <pre>
+ *   Result1
+ *     /BenchmarkA
+ *       /client1
+ *         /Probe1.csv
+ *       /client2
+ *         /Probe2.csv
+ *     /BenchmarkB
+ *         ...
+ * </pre>
+ */
+public class BenchmarkRunAnalyzer {
+  private final List<SensorData> benchmarks = new ArrayList<>();
+  private final List<ProbeResultParser> probes = new ArrayList<>();
+
+  /**
+   * Add a benchmark to be analyzed. The benchmark is expected to exist
+   * in both result directories passed to {@link #analyzeTestRun(File, File, Writer)}
+   */
+  public void addBenchmark(String name, String testResultDir, List<String> nodeNames) {
+    benchmarks.add(new SensorData(name, testResultDir, nodeNames));
+  }
+
+  /**
+   * Add a probe to produce a comparison for. The probe expects to find output files
+   * in the result directory for each node of each benchmark.
+   */
+  public void addProbe(ProbeResultParser probeResultParser) {
+    probes.add(probeResultParser);
+  }
+
+  public void analyzeTestRun(File testResultDir, File baselineResultDir, Writer output)
+      throws IOException {
+    PrintWriter stream = new PrintWriter(output);
+    for (SensorData benchmark : benchmarks) {
+      stream.println("-- " + benchmark.benchmarkName + " --");
+      for (ProbeResultParser probe : probes) {
+        stream.println(probe.getResultDescription());
+        for (String node : benchmark.nodesToParse) {
+          probe.parseResults(new File(new File(testResultDir, benchmark.benchmarkSubdirectory), node));
+        }
+        double testResult = probe.getProbeResult();
+        stream.println("Result: " + String.valueOf(testResult));
+        probe.reset();
+        for (String node : benchmark.nodesToParse) {
+          probe.parseResults(new File(new File(baselineResultDir, benchmark.benchmarkSubdirectory), node));
+        }
+        double baselineResult = probe.getProbeResult();
+        stream.println("Baseline: " + String.valueOf(baselineResult));
+        stream.println("Relative performance: " + String.valueOf(testResult / baselineResult));
+        stream.println();
+      }
+    }
+
+    stream.flush();
+  }
+
+  // TODO: depending on how run output is stored, this data may be excessive or insufficient
+  // The present assumption is each benchmark contains an arbitrarily named result directory
+  // containing subdirectories for each node.  Those subdirectories then contain the probe output
+  // files for the run, for that node.
+  private static class SensorData {
+    private final String benchmarkName;
+    private final String benchmarkSubdirectory;
+    private final List<String> nodesToParse;
+
+    public SensorData(String benchmarkName, String benchmarkSubdirectory, List<String> nodesNames) {
+      this.benchmarkName = benchmarkName;
+      this.benchmarkSubdirectory = benchmarkSubdirectory;
+      this.nodesToParse = nodesNames;
+    }
+  }
+
+}
diff --git a/harness/src/main/java/org/apache/geode/perftest/analysis/ProbeResultParser.java b/harness/src/main/java/org/apache/geode/perftest/analysis/ProbeResultParser.java
new file mode 100644
index 0000000..bcc76d4
--- /dev/null
+++ b/harness/src/main/java/org/apache/geode/perftest/analysis/ProbeResultParser.java
@@ -0,0 +1,34 @@
+/*
+ * 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.perftest.analysis;
+
+import java.io.File;
+import java.io.IOException;
+
+public interface ProbeResultParser {
+  // Given a output directory for a benchmark, parse out the data for the desired probe.  Note that
+  // this method may be passed several csv files for a run and is expected to appropriately
+  // aggregate the result of interest.
+  void parseResults(File benchmarkOutputDir) throws IOException;
+
+  // Reset the parser to a clean state where parseResults can be called again
+  void reset();
+
+  // Get a single float value summarizing the data for the probe.
+  double getProbeResult();
+
+  // Get a text description of what the probe result is depicting
+  String getResultDescription();
+}
diff --git a/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickPercentileSensorParser.java b/harness/src/main/java/org/apache/geode/perftest/yardstick/analysis/YardstickPercentileSensorParser.java
similarity index 75%
rename from harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickPercentileSensorParser.java
rename to harness/src/main/java/org/apache/geode/perftest/yardstick/analysis/YardstickPercentileSensorParser.java
index 429cb41..77af444 100644
--- a/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickPercentileSensorParser.java
+++ b/harness/src/main/java/org/apache/geode/perftest/yardstick/analysis/YardstickPercentileSensorParser.java
@@ -12,7 +12,7 @@
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
-package org.apache.geode.perftest.yardstick;
+package org.apache.geode.perftest.yardstick.analysis;
 
 import static java.lang.Math.abs;
 
@@ -22,12 +22,21 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
 
-public class YardstickPercentileSensorParser {
-  static final String sensorOutputFile = "PercentileProbe.csv";
+import org.yardstickframework.probes.PercentileProbe;
+
+import org.apache.geode.perftest.analysis.ProbeResultParser;
+
+/**
+ * Parses the output from {@link PercentileProbe} and reports the
+ * 99% percentile latency in microseconds.
+ */
+public class YardstickPercentileSensorParser implements ProbeResultParser {
+  public static final String sensorOutputFile = "PercentileProbe.csv";
+  public static final String probeResultDescription = "99th percentile latency";
 
   private class SensorBucket {
     public int latencyBucket;
-    public float bucketPercentage;
+    public double bucketPercentage;
 
     SensorBucket(String dataLine) throws IOException {
       String[] data = dataLine.split(",");
@@ -36,7 +45,7 @@ public class YardstickPercentileSensorParser {
       }
       try {
         latencyBucket = Integer.parseInt(data[0]);
-        bucketPercentage = Float.parseFloat(data[1]);
+        bucketPercentage = Double.parseDouble(data[1]);
       } catch (NumberFormatException e) {
         throw new IOException("Invalid data line: " + dataLine);
       }
@@ -60,6 +69,22 @@ public class YardstickPercentileSensorParser {
     }
   }
 
+  @Override
+  public void reset() {
+    buckets = new ArrayList<>();
+  }
+
+  @Override
+  // Default probe result is the 99th percentile latency for the benchmark
+  public double getProbeResult() {
+    return getPercentile(99);
+  }
+
+  @Override
+  public String getResultDescription() {
+    return probeResultDescription;
+  }
+
   private void normalizeBuckets() {
     float totalPercentage = 0;
     for (SensorBucket bucket : buckets) {
@@ -73,11 +98,11 @@ public class YardstickPercentileSensorParser {
     }
   }
 
-  public float getPercentile(int target) {
+  public double getPercentile(int target) {
     if (target < 0 || target > 100) {
       throw new RuntimeException("Percentile must be in the range (0, 100), invalid value: " + target);
     }
-    float targetPercent = target / 100f;
+    double targetPercent = target / 100.0;
     normalizeBuckets();
 
     if (buckets.size() == 1) {
@@ -86,7 +111,7 @@ public class YardstickPercentileSensorParser {
 
     SensorBucket[] bucketArray = buckets.toArray(new SensorBucket[buckets.size()]);
 
-    float accumulator = 0;
+    double accumulator = 0;
     int i = -1;
     while (targetPercent - accumulator > 0.0001) {
       ++i;
@@ -100,7 +125,7 @@ public class YardstickPercentileSensorParser {
         bucketArray[i + 1].latencyBucket - targetBucket.latencyBucket :
         targetBucket.latencyBucket - bucketArray[i - 1].latencyBucket;
 
-    float percentileLocationInTargetBucket = 1.0f - ((accumulator - targetPercent) / targetBucket.bucketPercentage);
+    double percentileLocationInTargetBucket = 1.0 - ((accumulator - targetPercent) / targetBucket.bucketPercentage);
 
     return targetBucket.latencyBucket + bucketSize * percentileLocationInTargetBucket;
   }
diff --git a/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickThroughputSensorParser.java b/harness/src/main/java/org/apache/geode/perftest/yardstick/analysis/YardstickThroughputSensorParser.java
similarity index 68%
rename from harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickThroughputSensorParser.java
rename to harness/src/main/java/org/apache/geode/perftest/yardstick/analysis/YardstickThroughputSensorParser.java
index 981080e..6c577f9 100644
--- a/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickThroughputSensorParser.java
+++ b/harness/src/main/java/org/apache/geode/perftest/yardstick/analysis/YardstickThroughputSensorParser.java
@@ -12,7 +12,7 @@
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
-package org.apache.geode.perftest.yardstick;
+package org.apache.geode.perftest.yardstick.analysis;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -21,28 +21,17 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-public class YardstickThroughputSensorParser {
-  static final String sensorOutputFile = "ThroughputLatencyProbe.csv";
+import org.yardstickframework.probes.ThroughputLatencyProbe;
 
-  private class SensorDatapoint {
-    public int second;
-    public float opsPerSec;
-    public float avgLatency;
+import org.apache.geode.perftest.analysis.ProbeResultParser;
 
-    SensorDatapoint(String dataLine) throws IOException {
-      String[] data = dataLine.split(",");
-      if (data.length != 3) {
-        throw new IOException("Invalid data line: " + dataLine);
-      }
-      try {
-        second = Integer.parseInt(data[0]);
-        opsPerSec = Float.parseFloat(data[1]);
-        avgLatency = Float.parseFloat(data[2]);
-      } catch (NumberFormatException e) {
-        throw new IOException("Invalid data line: " + dataLine);
-      }
-    }
-  }
+/**
+ * Parses the results from a {@link ThroughputLatencyProbe} and
+ * reports the average throughput in operations/second.
+ */
+public class YardstickThroughputSensorParser implements ProbeResultParser {
+  public static final String sensorOutputFile = "ThroughputLatencyProbe.csv";
+  public static final String probeResultDescription = "average ops/second";
 
   private List<SensorDatapoint> datapoints = new ArrayList<>();
 
@@ -61,11 +50,46 @@ public class YardstickThroughputSensorParser {
     }
   }
 
-  public float getAverageThroughput() {
-    float accumulator = 0;
+  @Override
+  public void reset() {
+    datapoints = new ArrayList<>();
+  }
+
+  @Override
+  public double getProbeResult() {
+    return getAverageThroughput();
+  }
+
+  @Override
+  public String getResultDescription() {
+    return probeResultDescription;
+  }
+
+  public double getAverageThroughput() {
+    double accumulator = 0;
     for (SensorDatapoint datapoint : datapoints) {
       accumulator += datapoint.opsPerSec;
     }
     return  accumulator / datapoints.size();
   }
+
+  private static class SensorDatapoint {
+    private int second;
+    private double opsPerSec;
+    private double avgLatency;
+
+    SensorDatapoint(String dataLine) throws IOException {
+      String[] data = dataLine.split(",");
+      if (data.length != 3) {
+        throw new IOException("Invalid data line: " + dataLine);
+      }
+      try {
+        second = Integer.parseInt(data[0]);
+        opsPerSec = Float.parseFloat(data[1]);
+        avgLatency = Float.parseFloat(data[2]);
+      } catch (NumberFormatException e) {
+        throw new IOException("Invalid data line: " + dataLine);
+      }
+    }
+  }
 }
diff --git a/harness/src/test/java/org/apache/geode/perftest/analysis/BenchmarkRunAnalyzerTest.java b/harness/src/test/java/org/apache/geode/perftest/analysis/BenchmarkRunAnalyzerTest.java
new file mode 100644
index 0000000..1911c0c
--- /dev/null
+++ b/harness/src/test/java/org/apache/geode/perftest/analysis/BenchmarkRunAnalyzerTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.perftest.analysis;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import org.apache.geode.perftest.analysis.BenchmarkRunAnalyzer;
+import org.apache.geode.perftest.yardstick.analysis.YardstickPercentileSensorParser;
+import org.apache.geode.perftest.yardstick.analysis.YardstickThroughputSensorParser;
+
+public class BenchmarkRunAnalyzerTest {
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  @Test
+  public void verifyResultHarvester() throws IOException {
+    final File testFolder = temporaryFolder.newFolder("testFolder");
+    final File testBenchmarkA1 = temporaryFolder.newFolder("testFolder","BenchmarkA","client1");
+    final File testBenchmarkA2 = temporaryFolder.newFolder("testFolder","BenchmarkA","client2");
+    final File testBenchmarkB1 = temporaryFolder.newFolder("testFolder","BenchmarkB","client1");
+    final File testBenchmarkB2 = temporaryFolder.newFolder("testFolder","BenchmarkB","client2");
+    final File baseFolder = temporaryFolder.newFolder("baseFolder");
+    final File baseBenchmarkA1 = temporaryFolder.newFolder("baseFolder","BenchmarkA","client1");
+    final File baseBenchmarkA2 = temporaryFolder.newFolder("baseFolder","BenchmarkA","client2");
+    final File baseBenchmarkB1 = temporaryFolder.newFolder("baseFolder","BenchmarkB","client1");
+    final File baseBenchmarkB2 = temporaryFolder.newFolder("baseFolder","BenchmarkB","client2");
+
+    populateThroughputCSV(testBenchmarkA1, new double[] {10, 15, 20, 25, 30});  // Avg 20
+    populatePercentileCSV(testBenchmarkA1, new double[] {0, 0, 99, 1});         // 200
+    populateThroughputCSV(testBenchmarkB1, new double[] {10, 15, 20, 25, 30, 35, 40});  // Avg 25
+    populatePercentileCSV(testBenchmarkB1, new double[] {0, 0, 0, 99, 1});      // 300
+    populateThroughputCSV(baseBenchmarkA1, new double[] {15, 20, 25, 30, 35});  // Avg 25
+    populatePercentileCSV(baseBenchmarkA1, new double[] {0, 99, 1});         // 100
+    populateThroughputCSV(baseBenchmarkB1, new double[] {10, 15, 20, 25, 30});  // Avg 20
+    populatePercentileCSV(baseBenchmarkB1, new double[] {0, 0, 0, 99, 1});      // 300
+
+    populateThroughputCSV(testBenchmarkA2, new double[] {10, 15, 20, 25, 30});  // Avg 20
+    populatePercentileCSV(testBenchmarkA2, new double[] {0, 0, 99, 1});         // 200
+    populateThroughputCSV(testBenchmarkB2, new double[] {10, 15, 20, 25, 30, 35, 40});  // Avg 25
+    populatePercentileCSV(testBenchmarkB2, new double[] {0, 0, 0, 99, 1});      // 300
+    populateThroughputCSV(baseBenchmarkA2, new double[] {15, 20, 25, 30, 35});  // Avg 25
+    populatePercentileCSV(baseBenchmarkA2, new double[] {0, 99, 1});         // 100
+    populateThroughputCSV(baseBenchmarkB2, new double[] {10, 15, 20, 25, 30});  // Avg 20
+    populatePercentileCSV(baseBenchmarkB2, new double[] {0, 0, 0, 99, 1});      // 300
+
+    List<String> nodes = new ArrayList(2);
+    nodes.add("client1");
+    nodes.add("client2");
+
+    BenchmarkRunAnalyzer harvester = new BenchmarkRunAnalyzer();
+    harvester.addBenchmark("Alpha", "BenchmarkA", nodes);
+    harvester.addBenchmark("Beta", "BenchmarkB", nodes);
+    harvester.addProbe(new YardstickThroughputSensorParser());
+    harvester.addProbe(new YardstickPercentileSensorParser());
+
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(4000);
+    StringWriter writer = new StringWriter();
+
+    harvester.analyzeTestRun(testFolder, baseFolder, writer);
+    System.out.println(writer.toString());
+    BufferedReader resultReader = new BufferedReader(new StringReader(writer.toString()));
+
+    validatedBenchmark(resultReader, "Alpha", 20, 300, 25, 200);
+    validatedBenchmark(resultReader, "Beta", 25, 400, 20, 400);
+  }
+
+  private void populateThroughputCSV(File targetDirectory, double[] perSecondThroughputs)
+      throws FileNotFoundException {
+    final File testFile = new File(targetDirectory, YardstickThroughputSensorParser.sensorOutputFile);
+    PrintStream output = new PrintStream(testFile);
+    for (int i = 0; i < perSecondThroughputs.length; ++i) {
+      output.println(String.format("%d,%f,%f", i, perSecondThroughputs[i], 1d));
+    }
+    output.close();
+  }
+
+  private void populatePercentileCSV(File targetDirectory, double[] hundredUsBuckets)
+      throws FileNotFoundException {
+    final File testFile = new File(targetDirectory, YardstickPercentileSensorParser.sensorOutputFile);
+    PrintStream output = new PrintStream(testFile);
+    for (int i = 0; i < hundredUsBuckets.length; ++i) {
+      output.println(String.format("%d,%f", 100*i, hundredUsBuckets[i]));
+    }
+    output.close();
+  }
+
+  private void validatedBenchmark(BufferedReader input, String benchmarkName, double testValA, double testValB, double baseValA, double baseValB)
+      throws IOException {
+    String line = input.readLine();
+    Assert.assertEquals("-- " + benchmarkName + " --", line);
+    validateProbe(input, YardstickThroughputSensorParser.probeResultDescription, testValA, baseValA);
+    validateProbe(input, YardstickPercentileSensorParser.probeResultDescription, testValB, baseValB);
+  }
+
+  private void validateProbe(BufferedReader input, String description, double testVal, double baseVal)
+      throws IOException {
+    String line = input.readLine();
+    Assert.assertEquals(description, line);
+    Scanner scanner = new Scanner(input.readLine());
+    while (!scanner.hasNextDouble()) {scanner.next();}
+    Assert.assertEquals(testVal, scanner.nextDouble(), 0.01 * testVal);
+    scanner = new Scanner(input.readLine());
+    while (!scanner.hasNextDouble()) {scanner.next();}
+    Assert.assertEquals(baseVal, scanner.nextDouble(), 0.01 * baseVal);
+    scanner = new Scanner(input.readLine());
+    while (!scanner.hasNextDouble()) {scanner.next();}
+    Assert.assertEquals(testVal / baseVal, scanner.nextDouble(), 0.1);
+    line = input.readLine();
+    Assert.assertEquals("", line);
+  }
+}
\ No newline at end of file
diff --git a/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickPercentileSensorParserTest.java b/harness/src/test/java/org/apache/geode/perftest/yardstick/analysis/YardstickPercentileSensorParserTest.java
similarity index 97%
rename from harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickPercentileSensorParserTest.java
rename to harness/src/test/java/org/apache/geode/perftest/yardstick/analysis/YardstickPercentileSensorParserTest.java
index bb55def..73e1385 100644
--- a/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickPercentileSensorParserTest.java
+++ b/harness/src/test/java/org/apache/geode/perftest/yardstick/analysis/YardstickPercentileSensorParserTest.java
@@ -12,7 +12,7 @@
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
-package org.apache.geode.perftest.yardstick;
+package org.apache.geode.perftest.yardstick.analysis;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -24,6 +24,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
+import org.apache.geode.perftest.yardstick.analysis.YardstickPercentileSensorParser;
+
 public class YardstickPercentileSensorParserTest {
   @Rule
   public TemporaryFolder temporaryFolder = new TemporaryFolder();
diff --git a/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickThroughputSensorParserTest.java b/harness/src/test/java/org/apache/geode/perftest/yardstick/analysis/YardstickThroughputSensorParserTest.java
similarity index 96%
rename from harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickThroughputSensorParserTest.java
rename to harness/src/test/java/org/apache/geode/perftest/yardstick/analysis/YardstickThroughputSensorParserTest.java
index 23c0114..7dfa9e6 100644
--- a/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickThroughputSensorParserTest.java
+++ b/harness/src/test/java/org/apache/geode/perftest/yardstick/analysis/YardstickThroughputSensorParserTest.java
@@ -13,7 +13,7 @@
  * the License.
  */
 
-package org.apache.geode.perftest.yardstick;
+package org.apache.geode.perftest.yardstick.analysis;
 
 import java.io.BufferedWriter;
 import java.io.File;
@@ -25,6 +25,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
+import org.apache.geode.perftest.yardstick.analysis.YardstickThroughputSensorParser;
+
 public class YardstickThroughputSensorParserTest {
   @Rule
   public TemporaryFolder temporaryFolder = new TemporaryFolder();