
com.splout.db.benchmark.SploutBenchmark Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of splout-hadoop Show documentation
Show all versions of splout-hadoop Show documentation
Splout is a read only, horizontally scalable SQL database that plays well with Hadoop.
package com.splout.db.benchmark;
/*
* #%L
* Splout SQL Hadoop library
* %%
* Copyright (C) 2012 Datasalt Systems S.L.
* %%
* Licensed 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.
* #L%
*/
import java.io.PrintStream;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* Generic benchmark implementation for Splout. Subclasses of {@link StressThreadImpl} must implement specialized SQL business logic.
*/
public class SploutBenchmark {
private long totalMillis;
private long reqPerSecond;
private long totalRows;
private int averageRows;
private int timeOuts = 0;
private double average;
private double max, min;
private double stdev, median, percen90;
private double gt10, gt50, gt100, gt250, gt500, gt1000, gt2500;
/**
* Subclasses of this class can be used for performing arbitrary benchmarks. They must perform queries when requested by {@link #nextQuery()} method.
*/
public static abstract class StressThreadImpl {
public abstract void init(Map context) throws Exception;
public abstract int nextQuery() throws Exception; // Performs the query and returns the number of rows processed
}
public void stressTest(final int nThreads, final int nQueries,
final Class extends StressThreadImpl> stressThreadClass, final Map context)
throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(nThreads);
final HistogramWithStats histo = new HistogramWithStats();
final AtomicLong totalRows = new AtomicLong(0);
long startTime = System.currentTimeMillis();
/*
* Instantiate pool of threads
*/
for(int k = 0; k < nThreads; k++) {
final int threadId = k;
service.submit(new Runnable() {
@Override
public void run() {
try {
/*
* Run a StressThreadImpl inside each Thread
*/
StressThreadImpl thisThread = stressThreadClass.newInstance();
// init
thisThread.init(context);
for(int i = 0; i < nQueries; i++) {
if(i % nThreads == threadId) { // distribute work
long start = System.currentTimeMillis();
int rowCount = 0;
try {
rowCount = thisThread.nextQuery();
} catch(java.net.SocketTimeoutException e) {
timeOuts ++;
}
long end = System.currentTimeMillis();
histo.add((end - start)); // add stat to histogram
totalRows.addAndGet(rowCount); // add total number of rows processed
}
}
} catch(Throwable t) {
t.printStackTrace();
throw new RuntimeException(t);
}
}
});
}
service.shutdown();
while(!service.isTerminated()) {
service.awaitTermination(500, TimeUnit.MILLISECONDS);
}
totalMillis = System.currentTimeMillis() - startTime;
/*
* Calculate and save stats for this run
*/
this.totalRows = totalRows.get();
averageRows = (int) (this.totalRows / nQueries);
average = histo.getAverage();
max = histo.getMax();
min = histo.getMin();
stdev = histo.getStdev();
median = -1;
percen90 = -1;
for(int i = (int) histo.getMin(); i <= histo.getMax(); i++) {
if(median == -1 && histo.getLeftAccumulatedProbability(i) > 0.5) {
median = i;
}
if(percen90 == -1 && histo.getLeftAccumulatedProbability(i) > 0.9) {
percen90 = i;
}
}
gt10 = histo.getRigthAccumulatedProbability(10);
gt50 = histo.getRigthAccumulatedProbability(50);
gt100 = histo.getRigthAccumulatedProbability(100);
gt250 = histo.getRigthAccumulatedProbability(250);
gt500 = histo.getRigthAccumulatedProbability(500);
gt1000 = histo.getRigthAccumulatedProbability(1000);
gt2500 = histo.getRigthAccumulatedProbability(2500);
reqPerSecond = nQueries / (totalMillis / 1000);
}
public void printStats(PrintStream outStream) {
outStream.println("Average query time\t" + average);
outStream.println("Max\t" + max);
outStream.println("Min\t" + min);
outStream.println("Stdev\t" + stdev);
outStream.println("Median\t" + median);
outStream.println("90 percentil\t" + percen90);
outStream.println("p > 10ms\t" + gt10);
outStream.println("p > 50ms\t" + gt50);
outStream.println("p > 100ms\t" + gt100);
outStream.println("p > 250ms\t" + gt250);
outStream.println("p > 500ms\t" + gt500);
outStream.println("p > 1000ms\t" + gt1000);
outStream.println("p > 2500ms\t" + gt2500);
outStream.println("Timeouts\t" + timeOuts);
outStream.println("Requests per second\t" + reqPerSecond);
outStream.println("Total rows\t" + totalRows);
outStream.println("Average rows\t" + averageRows);
}
// ------- Getters -------- //
/**
* After performing the benchmark, the total number of rows hit
*/
public long getTotalRows() {
return totalRows;
}
/**
* The average number of rows hit per query
*/
public int getAverageRows() {
return averageRows;
}
/**
* The average query response time
*/
public double getAverage() {
return average;
}
/**
* The maximum query response time
*/
public double getMax() {
return max;
}
/**
* The minimum query response time
*/
public double getMin() {
return min;
}
/**
* The standard deviation of the response time
*/
public double getStdev() {
return stdev;
}
/**
* The median query response time
*/
public double getMedian() {
return median;
}
/**
* The 90 percentil query response time
*/
public double getPercen90() {
return percen90;
}
/**
* The frequency of queries above 10 milliseconds
*/
public double getGt10() {
return gt10;
}
/**
* The frequency of queries above 50 milliseconds
*/
public double getGt50() {
return gt50;
}
/**
* The frequency of queries above 100 milliseconds
*/
public double getGt100() {
return gt100;
}
/**
* The frequency of queries above 250 milliseconds
*/
public double getGt250() {
return gt250;
}
/**
* The frequency of queries above 500 milliseconds
*/
public double getGt500() {
return gt500;
}
/**
* The frequency of queries above 1000 milliseconds
*/
public double getGt1000() {
return gt1000;
}
/**
* The frequency of queries above 2500 milliseconds
*/
public double getGt2500() {
return gt2500;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy