/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.benchmark; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.io.IOUtils; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.PMDException; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.SourceCodeProcessor; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageFilenameFilter; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.Parser; import net.sourceforge.pmd.util.FileUtil; import net.sourceforge.pmd.util.StringUtil; import net.sourceforge.pmd.util.datasource.DataSource; /** * * */ public class Benchmarker { private static final Map<String, BenchmarkResult> BENCHMARKS_BY_NAME = new HashMap<>(); private Benchmarker() { } /** * @param args * String[] * @param name * String * @return boolean */ private static boolean findBooleanSwitch(String[] args, String name) { for (int i = 0; i < args.length; i++) { if (args[i].equals(name)) { return true; } } return false; } /** * * @param args * String[] * @param name * String * @param defaultValue * String * @return String */ private static String findOptionalStringValue(String[] args, String name, String defaultValue) { for (int i = 0; i < args.length; i++) { if (args[i].equals(name)) { return args[i + 1]; } } return defaultValue; } /** * * @param args * String[] * @throws RuleSetNotFoundException * @throws IOException * @throws PMDException */ public static void main(String[] args) throws RuleSetNotFoundException, IOException, PMDException { String targetjdk = findOptionalStringValue(args, "--targetjdk", "1.4"); Language language = LanguageRegistry.getLanguage("Java"); LanguageVersion languageVersion = language.getVersion(targetjdk); if (languageVersion == null) { languageVersion = language.getDefaultVersion(); } String srcDir = findOptionalStringValue(args, "--source-directory", "/usr/local/java/src/java/lang/"); List<DataSource> dataSources = FileUtil.collectFiles(srcDir, new LanguageFilenameFilter(language)); boolean debug = findBooleanSwitch(args, "--debug"); boolean parseOnly = findBooleanSwitch(args, "--parse-only"); if (debug) { System.out.println("Using " + language.getName() + " " + languageVersion.getVersion()); } if (parseOnly) { Parser parser = PMD.parserFor(languageVersion, null); parseStress(parser, dataSources, debug); } else { String ruleset = findOptionalStringValue(args, "--ruleset", ""); if (debug) { System.out.println("Checking directory " + srcDir); } Set<RuleDuration> results = new TreeSet<>(); RuleSetFactory factory = new RuleSetFactory(); if (StringUtil.isNotEmpty(ruleset)) { stress(languageVersion, factory.createRuleSet(ruleset), dataSources, results, debug); } else { Iterator<RuleSet> i = factory.getRegisteredRuleSets(); while (i.hasNext()) { stress(languageVersion, i.next(), dataSources, results, debug); } } TextReport report = new TextReport(); report.generate(results, System.err); } } /** * @param parser * Parser * @param dataSources * List<DataSource> * @param debug * boolean * @throws IOException */ private static void parseStress(Parser parser, List<DataSource> dataSources, boolean debug) throws IOException { long start = System.currentTimeMillis(); for (DataSource dataSource : dataSources) { InputStreamReader reader = new InputStreamReader(dataSource.getInputStream()); try { parser.parse(dataSource.getNiceFileName(false, null), reader); } finally { IOUtils.closeQuietly(reader); } } if (debug) { long end = System.currentTimeMillis(); long elapsed = end - start; System.out.println("That took " + elapsed + " ms"); } } /** * @param languageVersion * LanguageVersion * @param ruleSet * RuleSet * @param dataSources * List<DataSource> * @param results * Set<RuleDuration> * @param debug * boolean * @throws PMDException * @throws IOException */ private static void stress(LanguageVersion languageVersion, RuleSet ruleSet, List<DataSource> dataSources, Set<RuleDuration> results, boolean debug) throws PMDException, IOException { final RuleSetFactory factory = new RuleSetFactory(); for (Rule rule: ruleSet.getRules()) { if (debug) { System.out.println("Starting " + rule.getName()); } final RuleSet working = factory.createSingleRuleRuleSet(rule); RuleSets ruleSets = new RuleSets(working); PMDConfiguration config = new PMDConfiguration(); config.setDefaultLanguageVersion(languageVersion); RuleContext ctx = new RuleContext(); long start = System.currentTimeMillis(); for (DataSource dataSource : dataSources) { Reader reader = new InputStreamReader(dataSource.getInputStream()); try { ctx.setSourceCodeFilename(dataSource.getNiceFileName(false, null)); new SourceCodeProcessor(config).processSourceCode(reader, ruleSets, ctx); } finally { IOUtils.closeQuietly(reader); } } long end = System.currentTimeMillis(); long elapsed = end - start; results.add(new RuleDuration(elapsed, rule)); if (debug) { System.out.println("Done timing " + rule.getName() + "; elapsed time was " + elapsed); } } } /** * @param type * Benchmark * @param time * long * @param count * long */ public static void mark(Benchmark type, long time, long count) { mark(type, null, time, count); } /** * * @param type * Benchmark * @param name * String * @param time * long * @param count * long */ public static synchronized void mark(Benchmark type, String name, long time, long count) { String typeName = type.name; if (typeName != null && name != null) { throw new IllegalArgumentException("Name cannot be given for type: " + type); } else if (typeName == null && name == null) { throw new IllegalArgumentException("Name is required for type: " + type); } else if (typeName == null) { typeName = name; } BenchmarkResult benchmarkResult = BENCHMARKS_BY_NAME.get(typeName); if (benchmarkResult == null) { benchmarkResult = new BenchmarkResult(type, typeName); BENCHMARKS_BY_NAME.put(typeName, benchmarkResult); } benchmarkResult.update(time, count); } public static void reset() { BENCHMARKS_BY_NAME.clear(); } public static Map<String, BenchmarkResult> values() { return BENCHMARKS_BY_NAME; } }