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:
Benchmark(const char * name,void (* fn)(int))38   Benchmark(const char* name, void (*fn)(int)) : name_(strdup(name)), fn_(fn) {
39     BenchmarkRegister(this);
40   }
Benchmark(const char * name)41   Benchmark(const char* name) : name_(strdup(name)), fn_(NULL) {}
42 
~Benchmark()43   virtual ~Benchmark() {
44     free(name_);
45   }
46 
Name()47   const char* Name() { return name_; }
ArgName()48   virtual const char* ArgName() { return NULL; }
RunFn(int iterations)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:
BenchmarkWantsArgBase(const char * name,void (* fn)(int,T))61   BenchmarkWantsArgBase(const char* name, void (*fn)(int, T)) : Benchmark(name) {
62     fn_arg_ = fn;
63   }
64 
Arg(const char * arg_name,T arg)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:
RunFn(int)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:
BenchmarkWithArg(const char * name,void (* fn)(int,T),const char * arg_name,T arg)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 
~BenchmarkWithArg()83   virtual ~BenchmarkWithArg() {
84     free(arg_name_);
85   }
86 
ArgName()87   virtual const char* ArgName() { return arg_name_; }
88 
89  protected:
RunFn(int iterations)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 
Arg(int arg)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 
BenchmarkFactory(const char * name,void (* fn)(int))118 static inline Benchmark* BenchmarkFactory(const char* name, void (*fn)(int)) {
119   return new Benchmark(name, fn);
120 }
121 
122 template <typename T>
BenchmarkFactory(const char * name,void (* fn)(int,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>
BenchmarkAddArg(::testing::Benchmark * b,const char * name,T arg)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