benchmark.h 3.7 KB

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