/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.benchmark;
import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.util.StringUtil;
/**
*
*
*/
public class TextReport implements BenchmarkReport {
private static final int TIME_COLUMN = 48;
private static final int NAME_COLUMN_WIDTH = 50;
private static final int VALUE_COLUMN_WIDTH = 8;
/**
*
* @param stressResults the durations from the stress test run
* @param out
* PrintStream
* @see BenchmarkReport#generate(Set, PrintStream)
*/
@Override
public void generate(Set<RuleDuration> stressResults, PrintStream out) {
out.println("=========================================================");
out.println("Rule\t\t\t\t\t\tTime in ms");
out.println("=========================================================");
for (RuleDuration result : stressResults) {
StringBuilder buffer = new StringBuilder(result.rule.getName());
while (buffer.length() < TIME_COLUMN) {
buffer.append(' ');
}
buffer.append(result.time);
out.println(out.toString());
}
out.println("=========================================================");
}
public void report(Map<String, BenchmarkResult> benchmarksByName) {
generate(benchmarksByName, System.out);
}
/**
*
* @param benchmarksByName
* @param out
* PrintStream
* @see BenchmarkReport#generate(Map, PrintStream)
*/
@Override
public void generate(Map<String, BenchmarkResult> benchmarksByName, PrintStream out) {
List<BenchmarkResult> results = new ArrayList<>(benchmarksByName.values());
long[] totalTime = new long[Benchmark.TotalPMD.index + 1];
long[] totalCount = new long[Benchmark.TotalPMD.index + 1];
for (BenchmarkResult benchmarkResult : results) {
totalTime[benchmarkResult.type.index] += benchmarkResult.getTime();
totalCount[benchmarkResult.type.index] += benchmarkResult.getCount();
if (benchmarkResult.type.index < Benchmark.MeasuredTotal.index) {
totalTime[Benchmark.MeasuredTotal.index] += benchmarkResult.getTime();
}
}
results.add(new BenchmarkResult(Benchmark.RuleTotal, totalTime[Benchmark.RuleTotal.index], 0));
results.add(new BenchmarkResult(Benchmark.RuleChainTotal, totalTime[Benchmark.RuleChainTotal.index], 0));
results.add(new BenchmarkResult(Benchmark.MeasuredTotal, totalTime[Benchmark.MeasuredTotal.index], 0));
results.add(new BenchmarkResult(Benchmark.NonMeasuredTotal,
totalTime[Benchmark.TotalPMD.index] - totalTime[Benchmark.MeasuredTotal.index], 0));
Collections.sort(results);
StringBuilderCR buf = new StringBuilderCR(PMD.EOL);
boolean writeRuleHeader = true;
boolean writeRuleChainRuleHeader = true;
long ruleCount = 0;
long ruleChainCount = 0;
for (BenchmarkResult benchmarkResult : results) {
StringBuilder buf2 = new StringBuilder(benchmarkResult.name);
buf2.append(':');
while (buf2.length() <= NAME_COLUMN_WIDTH) {
buf2.append(' ');
}
String result = MessageFormat.format("{0,number,0.000}",
Double.valueOf(benchmarkResult.getTime() / 1000000000.0));
buf2.append(StringUtil.lpad(result, VALUE_COLUMN_WIDTH));
if (benchmarkResult.type.index <= Benchmark.RuleChainRule.index) {
buf2.append(StringUtil
.lpad(MessageFormat.format("{0,number,###,###,###,###,###}", benchmarkResult.getCount()), 20));
}
switch (benchmarkResult.type) {
case Rule:
if (writeRuleHeader) {
writeRuleHeader = false;
buf.appendLn();
buf.appendLn("---------------------------------<<< Rules >>>---------------------------------");
buf.appendLn("Rule name Time (secs) # of Evaluations");
buf.appendLn();
}
ruleCount++;
break;
case RuleChainRule:
if (writeRuleChainRuleHeader) {
writeRuleChainRuleHeader = false;
buf.appendLn();
buf.appendLn("----------------------------<<< RuleChain Rules >>>----------------------------");
buf.appendLn("Rule name Time (secs) # of Visits");
buf.appendLn();
}
ruleChainCount++;
break;
case CollectFiles:
buf.appendLn();
buf.appendLn("--------------------------------<<< Summary >>>--------------------------------");
buf.appendLn("Segment Time (secs)");
buf.appendLn();
break;
case MeasuredTotal:
String s = MessageFormat.format("{0,number,###,###,###,###,###}", ruleCount);
String t = MessageFormat.format("{0,number,0.000}",
ruleCount == 0 ? 0 : total(totalTime, Benchmark.Rule, ruleCount));
buf.appendLn("Rule Average (", s, " rules):", StringUtil.lpad(t, 37 - s.length()));
s = MessageFormat.format("{0,number,###,###,###,###,###}", ruleChainCount);
t = MessageFormat.format("{0,number,0.000}",
ruleChainCount == 0 ? 0 : total(totalTime, Benchmark.RuleChainRule, ruleChainCount));
buf.appendLn("RuleChain Average (", s, " rules):", StringUtil.lpad(t, 32 - s.length()));
buf.appendLn();
buf.appendLn("-----------------------------<<< Final Summary >>>-----------------------------");
buf.appendLn("Total Time (secs)");
buf.appendLn();
break;
default:
// Do nothing
break;
}
buf.appendLn(buf2.toString());
}
out.print(buf.toString());
}
/**
*
* @param timeTotals
* long[]
* @param index
* Benchmark
* @param count
* long
* @return double
*/
private static double total(long[] timeTotals, Benchmark index, long count) {
return timeTotals[index.index] / 1000000000.0d / count;
}
}