blob: ec72b806dfdf2cc2bac8e8bc72dd24cf30d049a4 [file] [log] [blame]
Mark Salyzyn46abc522013-11-22 12:39:43 -08001/*
2 * Copyright (C) 2012-2013 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
27namespace testing {
28
29class Benchmark;
30template <typename T> class BenchmarkWantsArg;
31template <typename T> class BenchmarkWithArg;
32
33void BenchmarkRegister(Benchmark* bm);
34int PrettyPrintInt(char* str, int len, unsigned int arg);
35
36class 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
58template <typename T>
59class 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
75template <typename T>
76class 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
97template <typename T>
98class BenchmarkWantsArg : public BenchmarkWantsArgBase<T> {
99 public:
100 BenchmarkWantsArg<T>(const char* name, void (*fn)(int, T)) :
101 BenchmarkWantsArgBase<T>(name, fn) { }
102};
103
104template <>
105class 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
118static inline Benchmark* BenchmarkFactory(const char* name, void (*fn)(int)) {
119 return new Benchmark(name, fn);
120}
121
122template <typename T>
123static inline BenchmarkWantsArg<T>* BenchmarkFactory(const char* name, void (*fn)(int, T)) {
124 return new BenchmarkWantsArg<T>(name, fn);
125}
126
127} // namespace testing
128
129template <typename T>
130static 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
136void SetBenchmarkBytesProcessed(uint64_t);
137void ResetBenchmarkTiming(void);
138void StopBenchmarkTiming(void);
139void StartBenchmarkTiming(void);
140void StartBenchmarkTiming(uint64_t);
141void 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_