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