/**
* ICE Futures, US
*/
package test.org.helios.apmrouter.performance;
import org.helios.apmrouter.util.SimpleMath;
import org.helios.apmrouter.util.SystemClock.AggregatedElapsedTime;
import org.helios.apmrouter.util.SystemClock.ElapsedTime;
import java.lang.reflect.Method;
import java.math.BigDecimal;
/**
* <p>Title: AggregatedThreadBenchmarkResult</p>
* <p>Description: An aggregator for a collection of {@link ThreadBenchmarkResult}s </p>
* <p>Company: ICE Futures US</p>
* @author Whitehead (nicholas.whitehead@theice.com)
* @version $LastChangedRevision$
* <p><code>test.org.helios.apmrouter.performance.AggregatedThreadBenchmarkResult</code></p>
*/
public class AggregatedThreadBenchmarkResult {
/** The aggregated elapsed time */
public final AggregatedElapsedTime aggregatedElapsedTime;
/** The aggregated average of the average per op ms. */
public final long averageAvgPerOpMs;
/** The aggregated average of the min per op ms. */
public final long averageMinPerOpMs;
/** The aggregated average of the max per op ms. */
public final long averageMaxPerOpMs;
/** The aggregated average of the average per op ns. */
public final long averageAvgPerOpNs;
/** The aggregated average of the min per op ns. */
public final long averageMinPerOpNs;
/** The aggregated average of the max per op ns. */
public final long averageMaxPerOpNs;
/** The average number of blocks */
public final long averageBlocks;
/** The min number of blocks */
public final long minBlocks;
/** The max number of blocks */
public final long maxBlocks;
/** The average block time */
public final long averageBlockTime;
/** The min block time */
public final long minBlockTime;
/** The max block time */
public final long maxBlockTime;
/** The average number of waits */
public final long averageWaits;
/** The min number of waits */
public final long minWaits;
/** The max number of waits */
public final long maxWaits;
/** The average wait time */
public final long averageWaitTime;
/** The min wait time */
public final long minWaitTime;
/** The max wait time */
public final long maxWaitTime;
/** The average cpu time */
public final long averageCpuTime;
/** The min cpu time */
public final long minCpuTime;
/** The max cpu time */
public final long maxCpuTime;
/** The average cpu time per op */
public final long averageCpuTimePerOp;
/** The min cpu time per op */
public final long minCpuTimePerOp;
/** The max cpu time per op */
public final long maxCpuTimePerOp;
/** The number of long values */
public static final int LONG_VALUE_CNT = 24;
/**
* Creates a new AggregatedThreadBenchmarkResult
* @param time The aggregated elapsed time
* @param values The long values to initialize with
*/
private AggregatedThreadBenchmarkResult(AggregatedElapsedTime time, long[] values) {
aggregatedElapsedTime = time;
int index = 0;
averageAvgPerOpMs = values[index++];
averageMinPerOpMs = values[index++];
averageMaxPerOpMs = values[index++];
averageAvgPerOpNs = values[index++];
averageMinPerOpNs = values[index++];
averageMaxPerOpNs = values[index++];
averageBlocks = values[index++];
minBlocks = values[index++];
maxBlocks = values[index++];
averageBlockTime = values[index++];
minBlockTime = values[index++];
maxBlockTime = values[index++];
averageWaits = values[index++];
minWaits = values[index++];
maxWaits = values[index++];
averageWaitTime = values[index++];
minWaitTime = values[index++];
maxWaitTime = values[index++];
averageCpuTime = values[index++];
minCpuTime = values[index++];
maxCpuTime = values[index++];
averageCpuTimePerOp = values[index++];
minCpuTimePerOp = values[index++];
maxCpuTimePerOp = values[index++];
}
/**
* Returns an aggregate of the passed ThreadBenchmarkResult
* @param results the ThreadBenchmarkResult to aggregate
* @return the aggregate
*/
public static AggregatedThreadBenchmarkResult aggregate(ThreadBenchmarkResult...results) {
long[] args = new long[LONG_VALUE_CNT];
AggregatedElapsedTime aggregatedElapsedTime = AggregatedElapsedTime.aggregate(getElapsedTimes(results));
int index = 0;
long[] values = getAggregate("AvgPerOpMs", results);
args[index++] = values[0];
args[index++] = values[1];
args[index++] = values[2];
values = getAggregate("AvgPerOpNs", results);
args[index++] = values[0];
args[index++] = values[1];
args[index++] = values[2];
values = getAggregate("BlockCount", results);
args[index++] = values[0];
args[index++] = values[1];
args[index++] = values[2];
values = getAggregate("BlockTime", results);
args[index++] = values[0];
args[index++] = values[1];
args[index++] = values[2];
values = getAggregate("WaitCount", results);
args[index++] = values[0];
args[index++] = values[1];
args[index++] = values[2];
values = getAggregate("WaitTime", results);
args[index++] = values[0];
args[index++] = values[1];
args[index++] = values[2];
values = getAggregate("ElapsedSysCpu", results);
args[index++] = values[0];
args[index++] = values[1];
args[index++] = values[2];
final int opCount = results[0].opCount;
args[index++] = SimpleMath.avg(opCount, values[0]);
args[index++] = SimpleMath.avg(opCount, values[1]);
args[index++] = SimpleMath.avg(opCount, values[2]);
return new AggregatedThreadBenchmarkResult(aggregatedElapsedTime, args);
}
/**
* Returns all the elapsed times of the passed ThreadBenchmarkResults in an array
* @param results The ThreadBenchmarkResult to array the elapsed times for
* @return an array of elapsed times
*/
protected static ElapsedTime[] getElapsedTimes(ThreadBenchmarkResult...results) {
ElapsedTime[] times = new ElapsedTime[results.length];
for(int i = 0; i < results.length; i++) {
times[i] = results[i].getElapsedTime();
}
return times;
}
/**
* Returns the aggregate summary for the named value from the passed ThreadBenchmarkResults
* @param name The method accessor name
* @param results the results to aggregate from
* @return An array of longs containing <b><code>AVG, MIN, MAX</code></b>
*/
protected static long[] getAggregate(String name, ThreadBenchmarkResult...results) {
try {
long[] values = new long[results.length];
Method method = ThreadBenchmarkResult.class.getDeclaredMethod("get" + name);
for(int i = 0; i < results.length; i++) {
values[i] = ((Long)method.invoke(results[i])).longValue();
}
return aggregate(values);
} catch (Exception e) {
throw new RuntimeException("Failed to collect aggregate base value for [" + name + "]", e);
}
}
/**
* Creates an aggregate of the passed long values
* @param values the longs to aggregate
* @return An array of longs containing <b><code>AVG, MIN, MAX</code></b>.
*/
public static long[] aggregate(long...values) {
if(values==null || values.length<1) return new long[]{0,0,0};
long[] aggr = new long[3];
long max = Long.MIN_VALUE;
long min = Long.MAX_VALUE;
int cnt = 0;
BigDecimal total = new BigDecimal(0);
for(long value: values) {
if(value==-1) continue;
total = total.add(BigDecimal.valueOf(value));
if(value>max) max = value;
if(value<min) min = value;
cnt++;
}
try {
aggr[0] = (cnt!=0 && total.longValue()>0) ? (SimpleMath.avg(cnt, total.longValue())) : 0;
} catch (Exception e) {
System.err.println("Failed to compute average for a total of [" + total + "] and count [" + cnt + "]. Stack trace follows:");
e.printStackTrace(System.err);
}
aggr[1] = min==Long.MAX_VALUE ? -1 : min;
aggr[2] = max==Long.MIN_VALUE ? -1 : max;
return aggr;
}
/**
* {@inheritDoc}
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("AggregatedThreadBenchmarkResult [\n\taggregatedElapsedTime=");
builder.append(aggregatedElapsedTime);
builder.append("\n\taverageAvgPerOpMs=");
builder.append(averageAvgPerOpMs);
builder.append("\n\taverageMinPerOpMs=");
builder.append(averageMinPerOpMs);
builder.append("\n\taverageMaxPerOpMs=");
builder.append(averageMaxPerOpMs);
builder.append("\n\taverageAvgPerOpNs=");
builder.append(averageAvgPerOpNs);
builder.append("\n\taverageMinPerOpNs=");
builder.append(averageMinPerOpNs);
builder.append("\n\taverageMaxPerOpNs=");
builder.append(averageMaxPerOpNs);
builder.append("\n\taverageBlocks=");
builder.append(averageBlocks);
builder.append("\n\tminBlocks=");
builder.append(minBlocks);
builder.append("\n\tmaxBlocks=");
builder.append(maxBlocks);
builder.append("\n\taverageBlockTime=");
builder.append(averageBlockTime);
builder.append("\n\tminBlockTime=");
builder.append(minBlockTime);
builder.append("\n\tmaxBlockTime=");
builder.append(maxBlockTime);
builder.append("\n\taverageWaits=");
builder.append(averageWaits);
builder.append("\n\tminWaits=");
builder.append(minWaits);
builder.append("\n\tmaxWaits=");
builder.append(maxWaits);
builder.append("\n\taverageWaitTime=");
builder.append(averageWaitTime);
builder.append("\n\tminWaitTime=");
builder.append(minWaitTime);
builder.append("\n\tmaxWaitTime=");
builder.append(maxWaitTime);
builder.append("\n\taverageCpuTime=");
builder.append(averageCpuTime);
builder.append("\n\tminCpuTime=");
builder.append(minCpuTime);
builder.append("\n\tmaxCpuTime=");
builder.append(maxCpuTime);
builder.append("\n\taverageCpuTimePerOp=");
builder.append(averageCpuTimePerOp);
builder.append("\n\tminCpuTimePerOp=");
builder.append(minCpuTimePerOp);
builder.append("\n\tmaxCpuTimePerOp=");
builder.append(maxCpuTimePerOp);
builder.append("\n]");
return builder.toString();
}
}