1// Copyright 2009 The RE2 Authors. All Rights Reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#ifndef UTIL_BENCHMARK_H_
6#define UTIL_BENCHMARK_H_
7
8#include <stdint.h>
9#include <functional>
10
11#include "util/logging.h"
12#include "util/util.h"
13
14// Globals for the old benchmark API.
15void StartBenchmarkTiming();
16void StopBenchmarkTiming();
17void SetBenchmarkBytesProcessed(int64_t b);
18void SetBenchmarkItemsProcessed(int64_t i);
19
20namespace benchmark {
21
22// The new benchmark API implemented as a layer over the old benchmark API.
23// (Please refer to https://github.com/google/benchmark for documentation.)
24class State {
25 private:
26 class Iterator {
27 public:
28 // Benchmark code looks like this:
29 //
30 // for (auto _ : state) {
31 // // ...
32 // }
33 //
34 // We try to avoid compiler warnings about such variables being unused.
35 struct ATTRIBUTE_UNUSED Value {};
36
37 explicit Iterator(int64_t iters) : iters_(iters) {}
38
39 bool operator!=(const Iterator& that) const {
40 if (iters_ != that.iters_) {
41 return true;
42 } else {
43 // We are about to stop the loop, so stop timing.
44 StopBenchmarkTiming();
45 return false;
46 }
47 }
48
49 Value operator*() const {
50 return Value();
51 }
52
53 Iterator& operator++() {
54 --iters_;
55 return *this;
56 }
57
58 private:
59 int64_t iters_;
60 };
61
62 public:
63 explicit State(int64_t iters)
64 : iters_(iters), arg_(0), has_arg_(false) {}
65
66 State(int64_t iters, int64_t arg)
67 : iters_(iters), arg_(arg), has_arg_(true) {}
68
69 Iterator begin() {
70 // We are about to start the loop, so start timing.
71 StartBenchmarkTiming();
72 return Iterator(iters_);
73 }
74
75 Iterator end() {
76 return Iterator(0);
77 }
78
79 void SetBytesProcessed(int64_t b) { SetBenchmarkBytesProcessed(b); }
80 void SetItemsProcessed(int64_t i) { SetBenchmarkItemsProcessed(i); }
81 int64_t iterations() const { return iters_; }
82 // Pretend to support multiple arguments.
83 int64_t range(int pos) const { CHECK(has_arg_); return arg_; }
84
85 private:
86 int64_t iters_;
87 int64_t arg_;
88 bool has_arg_;
89
90 State(const State&) = delete;
91 State& operator=(const State&) = delete;
92};
93
94} // namespace benchmark
95
96namespace testing {
97
98class Benchmark {
99 public:
100 Benchmark(const char* name, void (*func)(benchmark::State&))
101 : name_(name),
102 func_([func](int iters, int arg) {
103 benchmark::State state(iters);
104 func(state);
105 }),
106 lo_(0),
107 hi_(0),
108 has_arg_(false) {
109 Register();
110 }
111
112 Benchmark(const char* name, void (*func)(benchmark::State&), int lo, int hi)
113 : name_(name),
114 func_([func](int iters, int arg) {
115 benchmark::State state(iters, arg);
116 func(state);
117 }),
118 lo_(lo),
119 hi_(hi),
120 has_arg_(true) {
121 Register();
122 }
123
124 // Pretend to support multiple threads.
125 Benchmark* ThreadRange(int lo, int hi) { return this; }
126
127 const char* name() const { return name_; }
128 const std::function<void(int, int)>& func() const { return func_; }
129 int lo() const { return lo_; }
130 int hi() const { return hi_; }
131 bool has_arg() const { return has_arg_; }
132
133 private:
134 void Register();
135
136 const char* name_;
137 std::function<void(int, int)> func_;
138 int lo_;
139 int hi_;
140 bool has_arg_;
141
142 Benchmark(const Benchmark&) = delete;
143 Benchmark& operator=(const Benchmark&) = delete;
144};
145
146} // namespace testing
147
148#define BENCHMARK(f) \
149 ::testing::Benchmark* _benchmark_##f = \
150 (new ::testing::Benchmark(#f, f))
151
152#define BENCHMARK_RANGE(f, lo, hi) \
153 ::testing::Benchmark* _benchmark_##f = \
154 (new ::testing::Benchmark(#f, f, lo, hi))
155
156#endif // UTIL_BENCHMARK_H_
157