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 explicit 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)) = /* NOLINT */ \
145 (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f) /* NOLINT */
146
147 #endif // BIONIC_BENCHMARK_H_
148