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