1
2
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
45
46
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
60
61
62
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
76
77
78
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<RuleDuration>();
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
124
125
126
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
149
150
151
152
153
154
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<String, BenchmarkResult>();
189
190
191
192
193
194
195 public static void mark(Benchmark type, long time, long count) {
196 mark(type, null, time, count);
197 }
198
199
200
201
202
203
204
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
230
231 public static Map<String, BenchmarkResult> values() {
232 return BENCHMARKS_BY_NAME;
233 }
234 }