benchmark.h revision 8d1fdb509305e93eb46d45a6dcd34bedd6dc0742
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
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_
148