package net.tuis.ubench;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* The UReport class encapsulates the results that are produced by
* {@link UBench#press(UMode, int, int, double, long, TimeUnit)} and exposes
* some convenient reporting methods.
*/
public class UReport {
/**
* A Comparator which sorts collections of UStats by the 95<sup>th</sup>
* percentile time (ascending - fastest first)
*/
public static final Comparator<UStats> BY_95PCTILE = Comparator.comparingLong(UStats::get95thPercentileNanos);
/**
* A Comparator which sorts collections of UStats by the 99<sup>th</sup>
* percentile time (ascending - fastest first)
*/
public static final Comparator<UStats> BY_99PCTILE = Comparator.comparingLong(UStats::get99thPercentileNanos);
/**
* A Comparator which sorts collections of UStats by the fastest time
* (ascending - fastest first)
*/
public static final Comparator<UStats> BY_FASTEST = Comparator.comparingLong(UStats::getFastestNanos);
/**
* A Comparator which sorts collections of UStats by the slowest time
* (ascending - quickest of the slowest first)
*/
public static final Comparator<UStats> BY_SLOWEST = Comparator.comparingLong(UStats::getFastestNanos);
/**
* A Comparator which sorts collections of UStats by the time consistency -
* calculated as the slowest/fastest ratio (ascending - most consistent
* first)
*/
public static final Comparator<UStats> BY_CONSISTENCY = Comparator.comparingDouble(s -> s.getSlowestNanos()
/ (s.getFastestNanos() * 1.0));
/**
* A Comparator which sorts collections of UStats by the average time
* (ascending - fastest first)
*/
public static final Comparator<UStats> BY_AVERAGE = Comparator.comparingDouble(UStats::getAverageRawNanos);
/**
* A Comparator which sorts collections of UStats by the order in which they
* were added to the UBench suite
*/
public static final Comparator<UStats> BY_ADDED = Comparator.comparingDouble(UStats::getIndex);
private final List<UStats> stats;
/**
* Construct a report container that includes all the specified statistics.
*
* @param stats
* the statistics to report on.
*/
public UReport(List<UStats> stats) {
super();
this.stats = stats;
}
/**
* Retrieve the raw statistics this Report would deliver, sorted in the
* order they were added to the benchmark.
*
* @return the raw statistics.
*/
public List<UStats> getStats() {
return getStats(null);
}
/**
* Retrieve the raw statistics this Report would deliver, sorted in the
* order specified (or the order they were added to the benchmark, if null).
*
* @param comparator
* The comparator to sort the results by.
* @return the statistics in the specified order.
*/
public List<UStats> getStats(final Comparator<UStats> comparator) {
List<UStats> result = new ArrayList<>(stats);
if (comparator != null) {
result.sort(comparator);
}
return result;
}
/**
* Simple helper method that prints the specified title, underlined with '='
* characters.
*
* @param writer
* the writer to write the title to.
* @param title
* the title to print (null or empty titles will be ignored).
* @throws IOException
* if the writer fails.
*/
public static void title(Writer writer, String title) throws IOException {
if (title == null || title.isEmpty()) {
return;
}
String out = String.format("%s\n%s\n\n", title,
Stream.generate(() -> "=").limit(title.length()).collect(Collectors.joining()));
writer.write(out);
}
/**
* Generate and print (System.out) the statistics report using the default (
* {@link #BY_ADDED}) sort order.
*
*/
public void report() {
reportSO(null, null);
}
/**
* Generate and print (System.out) the statistics report using the specified
* sort order.
*
* @param comparator
* the Comparator to sort the UStats by (see class constants for
* some useful suggestions)
*/
public void report(final Comparator<UStats> comparator) {
reportSO(null, comparator);
}
/**
* Generate and print (System.out) the statistics report with the supplied
* title, and using the default ({@link #BY_ADDED}) sort order.
*
* @param title
* the title to use (e.g. "Warmup", "Cached Files", etc.)
*/
public void report(final String title) {
reportSO(title, null);
}
/**
* Generate and print (System.out) the statistics report with the supplied
* title, and using the specified sort order.
*
* @param title
* the title to use (e.g. "Warmup", "Cached Files", etc.)
* @param comparator
* the Comparator to sort the UStats by (see class constants for
* some useful suggestions)
*/
public void report(final String title, final Comparator<UStats> comparator) {
reportSO(title, comparator);
}
/**
* Generate and print (System.out) the statistics report using the default (
* {@link #BY_ADDED}) sort order.
*
* @param writer
* the destination to report to
* @throws IOException
* if the writer destination fails
*/
public void report(final Writer writer) throws IOException {
report(writer, null, null);
}
/**
* Generate and print (System.out) the statistics report using the specified
* sort order.
*
* @param writer
* the destination to report to
* @param comparator
* the Comparator to sort the UStats by (see class constants for
* some useful suggestions)
* @throws IOException
* if the writer destination fails
*/
public void report(final Writer writer, final Comparator<UStats> comparator) throws IOException {
report(writer, null, comparator);
}
/**
* Generate and print (System.out) the statistics report with the supplied
* title, and using the default ({@link #BY_ADDED}) sort order.
*
* @param writer
* the destination to report to
* @param title
* the title to use (e.g. "Warmup", "Cached Files", etc.)
* @throws IOException
* if the writer destination fails
*/
public void report(final Writer writer, final String title) throws IOException {
report(writer, title, null);
}
/**
* Generate and print (System.out) the statistics report with the supplied
* title, and using the specified sort order.
*
* @param writer
* the destination to report to
* @param title
* the title to use (e.g. "Warmup", "Cached Files", etc.)
* @param comparator
* the Comparator to sort the UStats by (see class constants for
* some useful suggestions)
* @throws IOException
* if the writer destination fails
*/
public void report(final Writer writer, final String title, final Comparator<UStats> comparator) throws IOException {
title(writer, title);
long mintime = stats.stream().mapToLong(s -> s.getFastestNanos()).min().getAsLong();
TimeUnit tUnit = UStats.findBestUnit(mintime);
for (UStats s : getStats(comparator)) {
writer.write(s.formatResults(tUnit));
writer.write("\n");
}
}
private void reportSO(final String title, final Comparator<UStats> comparator) {
try (Writer w = new NonClosingSystemOut()) {
report(w, title, comparator);
} catch (IOException e) {
throw new IllegalStateException("Should never be an exception writing to System.out", e);
}
}
}