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. 15 void StartBenchmarkTiming(); 16 void StopBenchmarkTiming(); 17 void SetBenchmarkBytesProcessed(int64_t b); 18 void SetBenchmarkItemsProcessed(int64_t i); 19 20 namespace 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.) 24 class 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 Iterator(int64_t iters)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: State(int64_t iters)63 explicit State(int64_t iters) 64 : iters_(iters), arg_(0), has_arg_(false) {} 65 State(int64_t iters,int64_t arg)66 State(int64_t iters, int64_t arg) 67 : iters_(iters), arg_(arg), has_arg_(true) {} 68 begin()69 Iterator begin() { 70 // We are about to start the loop, so start timing. 71 StartBenchmarkTiming(); 72 return Iterator(iters_); 73 } 74 end()75 Iterator end() { 76 return Iterator(0); 77 } 78 SetBytesProcessed(int64_t b)79 void SetBytesProcessed(int64_t b) { SetBenchmarkBytesProcessed(b); } SetItemsProcessed(int64_t i)80 void SetItemsProcessed(int64_t i) { SetBenchmarkItemsProcessed(i); } iterations()81 int64_t iterations() const { return iters_; } 82 // Pretend to support multiple arguments. range(int pos)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 96 namespace testing { 97 98 class Benchmark { 99 public: Benchmark(const char * name,void (* func)(benchmark::State &))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 Benchmark(const char * name,void (* func)(benchmark::State &),int lo,int hi)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. ThreadRange(int lo,int hi)125 Benchmark* ThreadRange(int lo, int hi) { return this; } 126 name()127 const char* name() const { return name_; } func()128 const std::function<void(int, int)>& func() const { return func_; } lo()129 int lo() const { return lo_; } hi()130 int hi() const { return hi_; } has_arg()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