package xapi.test;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static xapi.util.X_String.toMetricSuffix;
import xapi.time.api.Clock;
import xapi.util.api.ReceivesValue;
public class Benchmark {
public static class Report implements ReceivesValue<List<Timing>>{
private PrintWriter out;
public Report(OutputStream out) {
this.out = new PrintWriter(out);
}
@Override
public void set(List<Timing> value) {
if (value.size()==0) {
out.println("Zero results; zero timing.");
return;
}
out.println("Calculating timing for "+value.size()+" results.");
//calculate max, min, mean and median
double max = 0, min = Double.MAX_VALUE, avg = 0;
double first = value.get(0).getTime();
double last = value.get(value.size()-1).getTime();
double size = value.size();//no integer math please!
for (Timing timing : value.toArray(new Timing[value.size()])) {
double time = timing.getTime();
max = Math.max(max, time);
min = Math.min(min, time);
avg += time / size;
}
int maxPos=0, minPos=0;
for (int i = value.size(); i-->0; ) {
if (value.get(i).getTime() == max) {
maxPos = i;
if (minPos > 0)break;
}
if (value.get(i).getTime() == min) {
minPos = i;
if (maxPos > 0)break;
}
}
out.println("Max: "+toMetricSuffix(max) + " ["+maxPos+"]");
out.println("Min: "+toMetricSuffix(min) + " [" +minPos+"]");
out.println("First: "+toMetricSuffix(first));
out.println("Last: "+toMetricSuffix(last));
out.println("Mean: "+toMetricSuffix(avg));
Collections.sort(value, new Comparator<Timing>() {
@Override
public int compare(Timing o1, Timing o2) {
return (int)((1000000)*(o1.getTime() - o2.getTime()));
}
});
double median = value.get((value.size()/2)).getTime();
out.println("Median: "+toMetricSuffix(median));
out.flush();
}
}
public class Timing extends Clock {
public Timing() {
}
public void finish() {
synchronized (Benchmark.this) {
done ++;
}
stop();
if (done == limit) {
System.out.println("Done "+done+" of "+limit);
onComplete.run();
}
}
}
final List<Timing> results;
private final int limit;
private volatile int done = 0;
private final Runnable onComplete;
public Benchmark(int iterations, ReceivesValue<Timing> job, final ReceivesValue<List<Timing>> onDone) {
results = new ArrayList<Timing>(iterations);
limit = iterations;
this.onComplete = new Runnable() {
@Override
public void run() {
onDone.set(results);
onComplete();
}
};
while (iterations --> 0) {
Timing t = new Timing();
results.add(t);
job.set(t);
}
onStarted();
}
protected void onStarted() {
}
protected void onComplete() {
}
}