View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.benchmark;
5   
6   import java.io.IOException;
7   import java.io.InputStreamReader;
8   import java.io.Reader;
9   import java.util.HashMap;
10  import java.util.Iterator;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.Set;
14  import java.util.TreeSet;
15  
16  import net.sourceforge.pmd.PMD;
17  import net.sourceforge.pmd.PMDConfiguration;
18  import net.sourceforge.pmd.PMDException;
19  import net.sourceforge.pmd.Rule;
20  import net.sourceforge.pmd.RuleContext;
21  import net.sourceforge.pmd.RuleSet;
22  import net.sourceforge.pmd.RuleSetFactory;
23  import net.sourceforge.pmd.RuleSetNotFoundException;
24  import net.sourceforge.pmd.RuleSets;
25  import net.sourceforge.pmd.SourceCodeProcessor;
26  import net.sourceforge.pmd.lang.Language;
27  import net.sourceforge.pmd.lang.LanguageFilenameFilter;
28  import net.sourceforge.pmd.lang.LanguageRegistry;
29  import net.sourceforge.pmd.lang.LanguageVersion;
30  import net.sourceforge.pmd.lang.Parser;
31  import net.sourceforge.pmd.util.FileUtil;
32  import net.sourceforge.pmd.util.StringUtil;
33  import net.sourceforge.pmd.util.datasource.DataSource;
34  
35  import org.apache.commons.io.IOUtils;
36  
37  /**
38   *
39   *
40   */
41  public class Benchmarker {
42  
43      /**
44       * @param args String[]
45       * @param name String
46       * @return boolean
47       */
48      private static boolean findBooleanSwitch(String[] args, String name) {
49          for (int i = 0; i < args.length; i++) {
50              if (args[i].equals(name)) {
51                  return true;
52              }
53          }
54          return false;
55      }
56  
57      /**
58       *
59       * @param args String[]
60       * @param name String
61       * @param defaultValue String
62       * @return String
63       */
64      private static String findOptionalStringValue(String[] args, String name, String defaultValue) {
65          for (int i = 0; i < args.length; i++) {
66              if (args[i].equals(name)) {
67                  return args[i + 1];
68              }
69          }
70          return defaultValue;
71      }
72  
73      /**
74       *
75       * @param args String[]
76       * @throws RuleSetNotFoundException
77       * @throws IOException
78       * @throws PMDException
79       */
80      public static void main(String[] args) throws RuleSetNotFoundException, IOException, PMDException {
81  
82          String targetjdk = findOptionalStringValue(args, "--targetjdk", "1.4");
83          Language language = LanguageRegistry.getLanguage("Java");
84          LanguageVersion languageVersion = language.getVersion(targetjdk);
85          if (languageVersion == null) {
86          	languageVersion = language.getDefaultVersion();
87          }
88  
89          String srcDir = findOptionalStringValue(args, "--source-directory", "/usr/local/java/src/java/lang/");
90          List<DataSource> dataSources = FileUtil.collectFiles(srcDir, new LanguageFilenameFilter(language));
91  
92          boolean debug = findBooleanSwitch(args, "--debug");
93          boolean parseOnly = findBooleanSwitch(args, "--parse-only");
94  
95          if (debug) {
96              System.out.println("Using " +language.getName() + " " + languageVersion.getVersion());
97          }
98          if (parseOnly) {
99          	Parser parser = PMD.parserFor(languageVersion, null);
100             parseStress(parser, dataSources, debug);
101         } else {
102             String ruleset = findOptionalStringValue(args, "--ruleset", "");
103             if (debug) {
104         		System.out.println("Checking directory " + srcDir);
105             }
106             Set<RuleDuration> results = new TreeSet<>();
107             RuleSetFactory factory = new RuleSetFactory();
108             if (StringUtil.isNotEmpty(ruleset)) {
109                 stress(languageVersion, factory.createRuleSet(ruleset), dataSources, results, debug);
110             } else {
111                 Iterator<RuleSet> i = factory.getRegisteredRuleSets();
112                 while (i.hasNext()) {
113                     stress(languageVersion, i.next(), dataSources, results, debug);
114                 }
115             }
116 
117             TextReport report = new TextReport();
118 			report.generate(results, System.err);
119         }
120     }
121 
122     /**
123      * @param parser Parser
124      * @param dataSources List<DataSource>
125      * @param debug boolean
126      * @throws IOException
127      */
128     private static void parseStress(Parser parser, List<DataSource> dataSources, boolean debug) throws IOException {
129 
130         long start = System.currentTimeMillis();
131 
132         for (DataSource dataSource: dataSources) {
133             parser.parse(
134             	dataSource.getNiceFileName(false, null),
135             	new InputStreamReader(dataSource.getInputStream()
136             	)
137             );
138         }
139 
140         if (debug) {
141         	long end = System.currentTimeMillis();
142         	long elapsed = end - start;
143         	System.out.println("That took " + elapsed + " ms");
144         }
145     }
146 
147     /**
148      * @param languageVersion LanguageVersion
149      * @param ruleSet RuleSet
150      * @param dataSources List<DataSource>
151      * @param results Set<RuleDuration>
152      * @param debug boolean
153      * @throws PMDException
154      * @throws IOException
155      */
156     private static void stress(LanguageVersion languageVersion, RuleSet ruleSet, List<DataSource> dataSources, Set<RuleDuration> results, boolean debug) throws PMDException, IOException {
157 
158         for (Rule rule: ruleSet.getRules()) {
159             if (debug) {
160             	System.out.println("Starting " + rule.getName());
161             }
162 
163             RuleSet working = new RuleSet();
164             working.addRule(rule);
165             RuleSets ruleSets = new RuleSets(working);
166 
167             PMDConfiguration config = new PMDConfiguration();
168             config.setDefaultLanguageVersion(languageVersion);
169 
170             RuleContext ctx = new RuleContext();
171             long start = System.currentTimeMillis();
172             Reader reader = null;
173             for (DataSource dataSource: dataSources) {
174             	reader = new InputStreamReader(dataSource.getInputStream());
175             	ctx.setSourceCodeFilename(dataSource.getNiceFileName(false, null));
176             	new SourceCodeProcessor(config).processSourceCode(reader, ruleSets, ctx);
177             	IOUtils.closeQuietly(reader);
178             	}
179             long end = System.currentTimeMillis();
180             long elapsed = end - start;
181             results.add(new RuleDuration(elapsed, rule));
182             if (debug) {
183             	System.out.println("Done timing " + rule.getName() + "; elapsed time was " + elapsed);
184             }
185         }
186     }
187 
188     private static final Map<String, BenchmarkResult> BENCHMARKS_BY_NAME = new HashMap<>();
189 
190     /**
191      * @param type Benchmark
192      * @param time long
193      * @param count long
194      */
195     public static void mark(Benchmark type, long time, long count) {
196         mark(type, null, time, count);
197     }
198 
199     /**
200      *
201      * @param type Benchmark
202      * @param name String
203      * @param time long
204      * @param count long
205      */
206     public synchronized static void mark(Benchmark type, String name, long time, long count) {
207         String typeName = type.name;
208         if (typeName != null && name != null) {
209             throw new IllegalArgumentException("Name cannot be given for type: " + type);
210         } else if (typeName == null && name == null) {
211             throw new IllegalArgumentException("Name is required for type: " + type);
212         } else if (typeName == null) {
213             typeName = name;
214         }
215         BenchmarkResult benchmarkResult = BENCHMARKS_BY_NAME.get(typeName);
216         if (benchmarkResult == null) {
217             benchmarkResult = new BenchmarkResult(type, typeName);
218             BENCHMARKS_BY_NAME.put(typeName, benchmarkResult);
219         }
220         benchmarkResult.update(time, count);
221     }
222 
223     public static void reset() {
224         BENCHMARKS_BY_NAME.clear();
225     }
226 
227     /**
228      *
229      * @return Map<String,BenchmarkResult>
230      */
231     public static Map<String, BenchmarkResult> values() {
232     	return BENCHMARKS_BY_NAME;
233     }
234 }