• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.caliper.runner;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 
21 import com.google.caliper.Benchmark;
22 import com.google.caliper.util.Util;
23 
24 import java.lang.reflect.Method;
25 import java.util.Arrays;
26 
27 /**
28  * Utilities for working with methods annotated by {@link Benchmark}.
29  */
30 final class BenchmarkMethods {
31   private static final Class<?>[] MACROBENCHMARK_PARAMS = new Class<?>[] {};
32   private static final Class<?>[] MICROBENCHMARK_PARAMS = new Class<?>[] {int.class};
33   private static final Class<?>[] PICOBENCHMARK_PARAMS = new Class<?>[] {long.class};
34 
BenchmarkMethods()35   private BenchmarkMethods() {}
36 
37   enum Type {
38     MACRO,
39     MICRO,
40     PICO;
41 
of(Method benchmarkMethod)42     static Type of(Method benchmarkMethod) {
43       Class<?>[] parameterTypes = benchmarkMethod.getParameterTypes();
44       if (Arrays.equals(parameterTypes, MACROBENCHMARK_PARAMS)) {
45         return MACRO;
46       } else if (Arrays.equals(parameterTypes, MICROBENCHMARK_PARAMS)) {
47         return MICRO;
48       } else if (Arrays.equals(parameterTypes, PICOBENCHMARK_PARAMS)) {
49         return PICO;
50       } else {
51         throw new IllegalArgumentException("invalid method parameters: " + benchmarkMethod);
52       }
53     }
54   }
55 
56   /**
57    * Several instruments look for benchmark methods like {@code timeBlah(int reps)}; this is the
58    * centralized code that identifies such methods.
59    *
60    * <p>This method does not check the correctness of the argument types.
61    */
isTimeMethod(Method method)62   static boolean isTimeMethod(Method method) {
63     return method.getName().startsWith("time") && Util.isPublic(method);
64   }
65 
66   /**
67    * For instruments that use {@link #isTimeMethod} to identify their methods, this method checks
68    * the {@link Method} appropriately.
69    */
checkTimeMethod(Method timeMethod)70   static Method checkTimeMethod(Method timeMethod) throws InvalidBenchmarkException {
71     checkArgument(isTimeMethod(timeMethod));
72     Class<?>[] parameterTypes = timeMethod.getParameterTypes();
73     if (!Arrays.equals(parameterTypes, new Class<?>[] {int.class})
74         && !Arrays.equals(parameterTypes, new Class<?>[] {long.class})) {
75       throw new InvalidBenchmarkException(
76           "Microbenchmark methods must accept a single int parameter: " + timeMethod.getName());
77     }
78 
79     // Static technically doesn't hurt anything, but it's just the completely wrong idea
80     if (Util.isStatic(timeMethod)) {
81       throw new InvalidBenchmarkException(
82           "Microbenchmark methods must not be static: " + timeMethod.getName());
83     }
84     return timeMethod;
85   }
86 }
87