/*
Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
this software, see the FLOSS License Exception
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation; version 2
of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this
program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
Floor, Boston, MA 02110-1301 USA
*/
package testsuite.perf;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import testsuite.BaseTestCase;
/**
* Base class for performance test cases. Handles statistics.
*
* @author Mark Matthews
*/
public abstract class BasePerfTest extends BaseTestCase {
// ~ Static fields/initializers
// ---------------------------------------------
/**
* Confidence interval lookup table, indexed by degrees of freedom at 95%.
*/
private static final double[] T95 = { 12.706, 4.303, 3.182, 2.776, 2.571,
2.447, 2.365, 2.306, 2.262, 2.228, 2.201, 2.179, 2.160, 2.145,
2.131, 2.120, 2.110, 2.101, 2.093, 2.086, 2.080, 2.074, 2.069,
2.064, 2.060, 2.056, 2.052, 2.048, 2.045, 2.042 };
/**
* Confidence interval lookup table, indexed by degrees of freedom at 99%.
*/
private static final double[] T99 = { 63.657, 9.925, 5.841, 4.604, 4.032,
3.707, 3.499, 3.355, 3.250, 3.169, 3.106, 3.055, 3.012, 2.977,
2.947, 2.921, 2.898, 2.878, 2.861, 2.845, 2.831, 2.819, 2.807,
2.797, 2.787, 2.779, 2.771, 2.763, 2.756, 2.750 };
static NumberFormat numberFormatter = NumberFormat.getInstance();
static {
numberFormatter.setMaximumFractionDigits(4);
numberFormatter.setMinimumFractionDigits(4);
}
// ~ Instance fields
// --------------------------------------------------------
/**
* List of values for each iteration
*/
private List<Double> testValuesList = new ArrayList<Double>();
private double confidenceLevel = 95; // 95% by default
private double confidenceValue = 0;
private double intervalWidth = 0.1;
private double meanValue = 0;
private double squareSumValue = 0;
private double sumValue = 0;
private double variationValue = 0;
/**
* The number of iterations that we have performed
*/
private int numIterations = 0;
// ~ Constructors
// -----------------------------------------------------------
/**
* Creates a new BasePerfTest object.
*
* @param name
* the testcase name to perform.
*/
public BasePerfTest(String name) {
super(name);
}
// ~ Methods
// ----------------------------------------------------------------
/**
* Returns the meanValue.
*
* @return double
*/
public double getMeanValue() {
return this.meanValue;
}
/**
* Sub-classes should override this to perform the operation to be measured.
*
* @throws Exception
* if an error occurs.
*/
protected abstract void doOneIteration() throws Exception;
/**
* Returns the current confidence level.
*
* @return the current confindence level.
*/
protected double getCurrentConfidence() {
return (this.intervalWidth - this.confidenceValue) * 100;
}
/**
* Returns the current margin of error.
*
* @return the current margin of error.
*/
protected double getMarginOfError() {
return getConfidenceLookup()
* (getStandardDeviationP() / Math.sqrt(this.numIterations));
}
/**
* Returns the current STDDEV.
*
* @return the current STDDEV
*/
protected double getStandardDeviationP() {
if (this.numIterations < 1) {
return 0;
}
return Math
.sqrt(((this.numIterations * this.squareSumValue) - (this.sumValue * this.sumValue))
/ (this.numIterations * this.numIterations));
}
/**
* Adds one test result to the statistics.
*
* @param value
* a single result representing the value being measured in the
* test.
*/
protected void addResult(double value) {
this.numIterations++;
this.testValuesList.add(new Double(value));
this.sumValue += value;
this.squareSumValue += (value * value);
this.meanValue = this.sumValue / this.numIterations;
this.variationValue = (this.squareSumValue / this.numIterations)
- (this.meanValue * this.meanValue);
// Can only have confidence when more than one test
// has been completed
if (this.numIterations > 1) {
this.confidenceValue = this.intervalWidth
- ((2.0 * getConfidenceLookup() * Math
.sqrt(this.variationValue
/ (this.numIterations - 1.0))) / this.meanValue);
}
}
/**
* Calls doIteration() the <code>numIterations</code> times, displaying
* the mean, std, margin of error and confidence level.
*
* @param num_iterations
* the number of iterations to perform ( < 30)
* @throws Exception
* if an error occurs.
*/
protected void doIterations(int num_iterations) throws Exception {
for (int i = 0; i < num_iterations; i++) {
doOneIteration();
}
}
/**
* Reports the current results to STDOUT, preceeded by
* <code>additionalMessage</code> if not null.
*
* @param additionalMessage
* the additional message to print, or null if no message.
*/
protected synchronized void reportResults(String additionalMessage) {
StringBuffer messageBuf = new StringBuffer();
if (additionalMessage != null) {
messageBuf.append(additionalMessage);
messageBuf.append(": ");
}
messageBuf.append(" mean: ");
messageBuf.append(numberFormatter.format(this.meanValue));
messageBuf.append(" stdevp: ");
messageBuf.append(numberFormatter.format(getStandardDeviationP()));
messageBuf.append(" m-o-e: ");
messageBuf.append(numberFormatter.format(getMarginOfError()));
System.out.println(messageBuf.toString());
}
private double getConfidenceLookup() {
if (this.confidenceLevel == 95) {
return T95[this.numIterations - 1];
} else if (this.confidenceLevel == 99) {
return T99[this.numIterations - 1];
} else {
throw new IllegalArgumentException(
"Confidence level must be 95 or 99");
}
}
}