blob: ae5c1a22899aae2f649496828cd98052a6358726 [file] [log] [blame]
Christopher Ferrisdf4942c2015-02-17 19:58:53 -08001/*
2 * Copyright (C) 2012 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#ifndef BENCHMARKS_BENCHMARK_H_
18#define BENCHMARKS_BENCHMARK_H_
19
20#include <regex.h>
21#include <stdint.h>
22
23#include <string>
24#include <vector>
25
26namespace testing {
27
28class Benchmark {
29public:
30 Benchmark() {
31 List().push_back(this);
32 }
33 virtual ~Benchmark() {}
34
35 virtual std::string Name() = 0;
36
Christopher Ferris339ac372015-02-20 18:31:06 -080037 virtual size_t RunAllArgs(std::vector<regex_t*>&) = 0;
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080038
39 void SetBenchmarkBytesProcessed(uint64_t bytes) { bytes_processed_ += bytes; }
40 void StopBenchmarkTiming();
41 void StartBenchmarkTiming();
42
43 // Run all of the benchmarks that have registered.
Christopher Ferris339ac372015-02-20 18:31:06 -080044 static size_t RunAll(std::vector<regex_t*>&);
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080045
46 static std::vector<Benchmark*>& List();
47
Greg Hackmann567bfb32015-02-20 11:00:14 -080048 static int MaxNameColumnWidth();
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080049
50protected:
Christopher Ferris339ac372015-02-20 18:31:06 -080051 virtual size_t NameColumnWidth() = 0;
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080052
53 uint64_t bytes_processed_;
54 uint64_t total_time_ns_;
55 uint64_t start_time_ns_;
Christopher Ferris339ac372015-02-20 18:31:06 -080056
57 static bool header_printed_;
58
59 static void PrintHeader();
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080060};
61
62template <typename T>
63class BenchmarkT : public Benchmark {
64public:
65 BenchmarkT() {}
66 virtual ~BenchmarkT() {}
67
68protected:
Christopher Ferris339ac372015-02-20 18:31:06 -080069 bool ShouldRun(std::vector<regex_t*>&, T arg);
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080070 void RunWithArg(T arg);
71 virtual void RunIterations(int, T) = 0;
72 virtual std::string GetNameStr(T) = 0;
73};
74
75class BenchmarkWithoutArg : public BenchmarkT<void*> {
76public:
77 BenchmarkWithoutArg() {}
78 virtual ~BenchmarkWithoutArg() {}
79
80protected:
Christopher Ferris339ac372015-02-20 18:31:06 -080081 virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
82 size_t benchmarks_run = 0;
83 if (BenchmarkT<void*>::ShouldRun(regs, nullptr)) {
84 PrintHeader();
85 RunWithArg(nullptr);
86 benchmarks_run++;
87 }
88 return benchmarks_run;
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080089 }
90
91 virtual void RunIterations(int iters, void*) override {
92 Run(iters);
93 }
94
95 virtual void Run(int) = 0;
96
Christopher Ferris339ac372015-02-20 18:31:06 -080097 virtual size_t NameColumnWidth() override {
98 return Name().size();
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080099 }
100
101 virtual std::string GetNameStr(void *) override;
102};
103
104template<typename T>
105class BenchmarkWithArg : public BenchmarkT<T> {
106public:
107 BenchmarkWithArg() {}
108 virtual ~BenchmarkWithArg() {}
109
110 BenchmarkWithArg* Arg(T arg) {
111 args_.push_back(arg);
112 return this;
113 }
114
115protected:
Christopher Ferris339ac372015-02-20 18:31:06 -0800116 virtual size_t NameColumnWidth() override {
117 size_t max = 0;
118 for (const auto& arg : args_) {
119 max = std::max(max, GetNameStr(arg).size());
Christopher Ferrisdf4942c2015-02-17 19:58:53 -0800120 }
121 return max;
122 }
123
124 std::string GetNameStr(T arg) override;
125
Christopher Ferris339ac372015-02-20 18:31:06 -0800126 virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
127 size_t benchmarks_run = 0;
128 for (T& arg : args_) {
129 if (BenchmarkT<T>::ShouldRun(regs, arg)) {
130 Benchmark::PrintHeader();
131 BenchmarkT<T>::RunWithArg(arg);
132 benchmarks_run++;
133 }
Christopher Ferrisdf4942c2015-02-17 19:58:53 -0800134 }
Christopher Ferris339ac372015-02-20 18:31:06 -0800135 return benchmarks_run;
Christopher Ferrisdf4942c2015-02-17 19:58:53 -0800136 }
137
138 virtual void RunIterations(int iters, T arg) override {
139 Run(iters, arg);
140 }
141
142 virtual void Run(int iters, T arg) = 0;
143
144private:
145 std::vector<T> args_;
146};
147
148} // namespace testing
149
150#define BENCHMARK_START(f, super_class) \
151 class f : public super_class { \
152 public: \
153 f() {} \
154 virtual ~f() {} \
155 virtual std::string Name() override { return #f; } \
156
157#define BENCHMARK_NO_ARG(f) \
158 BENCHMARK_START(f, ::testing::BenchmarkWithoutArg) \
159 virtual void Run(int) override; \
160 }; \
161 static ::testing::Benchmark* __benchmark_##f = new f()
162
163#define BENCHMARK_WITH_ARG(f, arg_type) \
164 BENCHMARK_START(f, ::testing::BenchmarkWithArg<arg_type>) \
165 virtual void Run(int, arg_type) override; \
166 }; \
167 static ::testing::BenchmarkWithArg<arg_type>* __benchmark_##f = (new f())
168
169#endif // BENCHMARKS_BENCHMARK_H_