1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.perfidix;
28
29 import java.lang.reflect.Method;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.Hashtable;
33 import java.util.LinkedHashSet;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Random;
37 import java.util.Set;
38
39 import org.perfidix.AbstractConfig.StandardConfig;
40 import org.perfidix.annotation.AfterBenchClass;
41 import org.perfidix.annotation.BeforeBenchClass;
42 import org.perfidix.annotation.Bench;
43 import org.perfidix.element.AbstractMethodArrangement;
44 import org.perfidix.element.BenchmarkElement;
45 import org.perfidix.element.BenchmarkExecutor;
46 import org.perfidix.element.BenchmarkMethod;
47 import org.perfidix.exceptions.PerfidixMethodCheckException;
48 import org.perfidix.exceptions.PerfidixMethodInvocationException;
49 import org.perfidix.meter.AbstractMeter;
50 import org.perfidix.result.BenchmarkResult;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 public final class Benchmark {
91
92
93 private transient final Set<Class<?>> clazzes;
94
95
96 private transient final Set<Object> objects;
97
98
99 private transient static final Random RAN = new Random();
100
101
102 private transient final AbstractConfig conf;
103
104
105
106
107
108
109
110 public Benchmark(final AbstractConfig paramConf) {
111 conf = paramConf;
112 this.clazzes = new LinkedHashSet<Class<?>>();
113 this.objects = new LinkedHashSet<Object>();
114
115 }
116
117
118
119
120 public Benchmark() {
121 this(new StandardConfig());
122 }
123
124
125
126
127
128
129
130
131 public void add(final Class<?> clazz) {
132 if (this.clazzes.contains(clazz)) {
133 throw new IllegalArgumentException("Only one class-instance per benchmark allowed");
134 } else {
135 this.clazzes.add(clazz);
136 }
137 }
138
139
140
141
142
143
144
145
146 public void add(final Object obj) {
147 final Class<?> clazz = obj.getClass();
148
149 if (this.clazzes.contains(clazz)) {
150 throw new IllegalArgumentException("Only one class-instance per benchmark allowed");
151 } else {
152 this.clazzes.add(clazz);
153 this.objects.add(obj);
154 }
155 }
156
157
158
159
160
161
162 public Map<BenchmarkMethod, Integer> getNumberOfMethodsAndRuns() {
163 final Map<BenchmarkMethod, Integer> returnVal = new HashMap<BenchmarkMethod, Integer>();
164 final List<BenchmarkMethod> meths = getBenchmarkMethods();
165 for (final BenchmarkMethod meth : meths) {
166 int numberOfRuns = BenchmarkMethod.getNumberOfAnnotatedRuns(meth.getMethodToBench());
167 if (numberOfRuns == Bench.NONE_RUN) {
168 numberOfRuns = conf.getRuns();
169 }
170 returnVal.put(meth, numberOfRuns);
171 }
172 return returnVal;
173 }
174
175
176
177
178
179
180 public BenchmarkResult run() {
181 final BenchmarkResult res = new BenchmarkResult(conf.getListener());
182 BenchmarkExecutor.initialize(conf, res);
183
184
185 final List<BenchmarkElement> elements = getBenchmarkElements();
186
187
188 final AbstractMethodArrangement arrangement =
189 AbstractMethodArrangement.getMethodArrangement(elements, conf.getArrangement());
190
191
192 final Map<Class<?>, Object> instantiatedObj = instantiateMethods(res);
193
194
195 final Map<Class<?>, Object> objectsToExecute = executeBeforeBenchClass(instantiatedObj, res);
196
197
198 for (final BenchmarkElement elem : arrangement) {
199
200 if (RAN.nextDouble() < conf.getGcProb()) {
201 System.gc();
202 }
203
204 final BenchmarkExecutor exec = BenchmarkExecutor.getExecutor(elem);
205
206 final Object obj = objectsToExecute.get(elem.getMeth().getMethodToBench().getDeclaringClass());
207
208 if (obj != null) {
209 exec.executeBeforeMethods(obj);
210 exec.executeBench(obj);
211 exec.executeAfterMethods(obj);
212 }
213 }
214
215
216 tearDownObjectsToExecute(objectsToExecute, res);
217 return res;
218 }
219
220
221
222
223
224
225
226
227
228
229
230 private Map<Class<?>, Object> instantiateMethods(final BenchmarkResult res) {
231
232 final Map<Class<?>, Object> objectsToUse = new Hashtable<Class<?>, Object>();
233
234
235 for (final Object obj : this.objects) {
236 final Class<?> clazz = obj.getClass();
237 objectsToUse.put(clazz, obj);
238 }
239
240
241 for (final Class<?> clazz : clazzes) {
242
243
244 if (!objectsToUse.containsKey(clazz)) {
245 try {
246 final Object obj = clazz.newInstance();
247 objectsToUse.put(clazz, obj);
248
249 } catch (final InstantiationException e) {
250 res.addException(new PerfidixMethodInvocationException(e, BeforeBenchClass.class));
251 } catch (final IllegalAccessException e) {
252 res.addException(new PerfidixMethodInvocationException(e, BeforeBenchClass.class));
253 }
254
255 }
256 }
257
258 return objectsToUse;
259 }
260
261
262
263
264
265
266
267
268
269
270 private Map<Class<?>, Object> executeBeforeBenchClass(final Map<Class<?>, Object> instantiatedObj,
271 final BenchmarkResult res) {
272
273 final Map<Class<?>, Object> returnVal = new Hashtable<Class<?>, Object>();
274
275
276 for (final Class<?> clazz : instantiatedObj.keySet()) {
277
278 final Object objectToUse = instantiatedObj.get(clazz);
279
280 Method beforeClassMeth = null;
281 boolean continueVal = true;
282 try {
283 beforeClassMeth =
284 BenchmarkMethod.findAndCheckAnyMethodByAnnotation(clazz, BeforeBenchClass.class);
285
286
287 } catch (final PerfidixMethodCheckException e) {
288 res.addException(e);
289 continueVal = false;
290 }
291
292 if (continueVal) {
293 if (beforeClassMeth == null) {
294
295
296 returnVal.put(clazz, objectToUse);
297 } else {
298
299
300 final PerfidixMethodCheckException beforeByCheck =
301 BenchmarkExecutor.checkMethod(objectToUse, BeforeBenchClass.class, beforeClassMeth);
302 if (beforeByCheck == null) {
303 final PerfidixMethodInvocationException beforeByInvok =
304 BenchmarkExecutor.invokeMethod(objectToUse, BeforeBenchClass.class,
305 beforeClassMeth);
306 if (beforeByInvok == null) {
307 returnVal.put(clazz, objectToUse);
308 } else {
309 res.addException(beforeByInvok);
310 }
311 } else {
312 res.addException(beforeByCheck);
313 }
314 }
315 }
316 }
317 return returnVal;
318 }
319
320
321
322
323
324
325
326
327
328
329 private void tearDownObjectsToExecute(final Map<Class<?>, Object> objects, final BenchmarkResult res) {
330
331
332 for (final Class<?> clazz : objects.keySet()) {
333 final Object objectToUse = objects.get(clazz);
334 if (objectToUse != null) {
335
336 Method afterClassMeth = null;
337 try {
338 afterClassMeth =
339 BenchmarkMethod.findAndCheckAnyMethodByAnnotation(clazz, AfterBenchClass.class);
340 } catch (final PerfidixMethodCheckException e) {
341 res.addException(e);
342 }
343
344
345 if (afterClassMeth != null) {
346 final PerfidixMethodCheckException afterByCheck =
347 BenchmarkExecutor.checkMethod(objectToUse, AfterBenchClass.class, afterClassMeth);
348 if (afterByCheck == null) {
349 final PerfidixMethodInvocationException afterByInvok =
350 BenchmarkExecutor
351 .invokeMethod(objectToUse, AfterBenchClass.class, afterClassMeth);
352 if (afterByInvok != null) {
353 res.addException(afterByInvok);
354 }
355 } else {
356 res.addException(afterByCheck);
357 }
358 }
359 }
360 }
361 }
362
363
364
365
366
367
368 public List<BenchmarkMethod> getBenchmarkMethods() {
369
370 final List<BenchmarkMethod> elems = new ArrayList<BenchmarkMethod>();
371
372 for (final Class<?> clazz : clazzes) {
373 for (final Method meth : clazz.getDeclaredMethods()) {
374
375 if (BenchmarkMethod.isBenchmarkable(meth)) {
376 final BenchmarkMethod benchmarkMeth = new BenchmarkMethod(meth);
377 elems.add(benchmarkMeth);
378 }
379 }
380 }
381 return elems;
382 }
383
384
385
386
387
388
389
390 public List<BenchmarkElement> getBenchmarkElements() {
391
392 final List<BenchmarkElement> elems = new ArrayList<BenchmarkElement>();
393
394 final List<BenchmarkMethod> meths = getBenchmarkMethods();
395
396 for (final BenchmarkMethod meth : meths) {
397 int numberOfRuns = BenchmarkMethod.getNumberOfAnnotatedRuns(meth.getMethodToBench());
398 if (numberOfRuns == Bench.NONE_RUN) {
399 numberOfRuns = conf.getRuns();
400 }
401
402
403
404 for (int i = 0; i < numberOfRuns; i++) {
405 elems.add(new BenchmarkElement(meth));
406 }
407 }
408
409 return elems;
410 }
411 }