1 /* 2 * Copyright (C) 2012-2014 The Android Open Source Project 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 #include <stdint.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 #include <vector> 23 24 #ifndef BIONIC_BENCHMARK_H_ 25 #define BIONIC_BENCHMARK_H_ 26 27 namespace testing { 28 29 class Benchmark; 30 template <typename T> class BenchmarkWantsArg; 31 template <typename T> class BenchmarkWithArg; 32 33 void BenchmarkRegister(Benchmark* bm); 34 int PrettyPrintInt(char* str, int len, unsigned int arg); 35 36 class Benchmark { 37 public: 38 Benchmark(const char* name, void (*fn)(int)) : name_(strdup(name)), fn_(fn) { 39 BenchmarkRegister(this); 40 } 41 Benchmark(const char* name) : name_(strdup(name)), fn_(NULL) {} 42 43 virtual ~Benchmark() { 44 free(name_); 45 } 46 47 const char* Name() { return name_; } 48 virtual const char* ArgName() { return NULL; } 49 virtual void RunFn(int iterations) { fn_(iterations); } 50 51 protected: 52 char* name_; 53 54 private: 55 void (*fn_)(int); 56 }; 57 58 template <typename T> 59 class BenchmarkWantsArgBase : public Benchmark { 60 public: 61 BenchmarkWantsArgBase(const char* name, void (*fn)(int, T)) : Benchmark(name) { 62 fn_arg_ = fn; 63 } 64 65 BenchmarkWantsArgBase<T>* Arg(const char* arg_name, T arg) { 66 BenchmarkRegister(new BenchmarkWithArg<T>(name_, fn_arg_, arg_name, arg)); 67 return this; 68 } 69 70 protected: 71 virtual void RunFn(int) { printf("can't run arg benchmark %s without arg\n", Name()); } 72 void (*fn_arg_)(int, T); 73 }; 74 75 template <typename T> 76 class BenchmarkWithArg : public BenchmarkWantsArg<T> { 77 public: 78 BenchmarkWithArg(const char* name, void (*fn)(int, T), const char* arg_name, T arg) : 79 BenchmarkWantsArg<T>(name, fn), arg_(arg) { 80 arg_name_ = strdup(arg_name); 81 } 82 83 virtual ~BenchmarkWithArg() { 84 free(arg_name_); 85 } 86 87 virtual const char* ArgName() { return arg_name_; } 88 89 protected: 90 virtual void RunFn(int iterations) { BenchmarkWantsArg<T>::fn_arg_(iterations, arg_); } 91 92 private: 93 T arg_; 94 char* arg_name_; 95 }; 96 97 template <typename T> 98 class BenchmarkWantsArg : public BenchmarkWantsArgBase<T> { 99 public: 100 BenchmarkWantsArg<T>(const char* name, void (*fn)(int, T)) : 101 BenchmarkWantsArgBase<T>(name, fn) { } 102 }; 103 104 template <> 105 class BenchmarkWantsArg<int> : public BenchmarkWantsArgBase<int> { 106 public: 107 BenchmarkWantsArg<int>(const char* name, void (*fn)(int, int)) : 108 BenchmarkWantsArgBase<int>(name, fn) { } 109 110 BenchmarkWantsArg<int>* Arg(int arg) { 111 char arg_name[100]; 112 PrettyPrintInt(arg_name, sizeof(arg_name), arg); 113 BenchmarkRegister(new BenchmarkWithArg<int>(name_, fn_arg_, arg_name, arg)); 114 return this; 115 } 116 }; 117 118 static inline Benchmark* BenchmarkFactory(const char* name, void (*fn)(int)) { 119 return new Benchmark(name, fn); 120 } 121 122 template <typename T> 123 static inline BenchmarkWantsArg<T>* BenchmarkFactory(const char* name, void (*fn)(int, T)) { 124 return new BenchmarkWantsArg<T>(name, fn); 125 } 126 127 } // namespace testing 128 129 template <typename T> 130 static inline void BenchmarkAddArg(::testing::Benchmark* b, const char* name, T arg) { 131 ::testing::BenchmarkWantsArg<T>* ba; 132 ba = static_cast< ::testing::BenchmarkWantsArg<T>* >(b); 133 ba->Arg(name, arg); 134 } 135 136 void SetBenchmarkBytesProcessed(uint64_t); 137 void ResetBenchmarkTiming(void); 138 void StopBenchmarkTiming(void); 139 void StartBenchmarkTiming(void); 140 void StartBenchmarkTiming(uint64_t); 141 void StopBenchmarkTiming(uint64_t); 142 143 #define BENCHMARK(f) \ 144 static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \ 145 (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f) 146 147 #endif // BIONIC_BENCHMARK_H_ 148