1 /* 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 26 namespace testing { 27 28 class Benchmark { 29 public: Benchmark()30 Benchmark() { 31 List().push_back(this); 32 } ~Benchmark()33 virtual ~Benchmark() {} 34 35 virtual std::string Name() = 0; 36 37 virtual size_t RunAllArgs(std::vector<regex_t*>&) = 0; 38 SetBenchmarkBytesProcessed(uint64_t bytes)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. 44 static size_t RunAll(std::vector<regex_t*>&); 45 46 static std::vector<Benchmark*>& List(); 47 48 static int MaxNameColumnWidth(); 49 50 protected: 51 virtual size_t NameColumnWidth() = 0; 52 53 uint64_t bytes_processed_; 54 uint64_t total_time_ns_; 55 uint64_t start_time_ns_; 56 57 static bool header_printed_; 58 59 static void PrintHeader(); 60 }; 61 62 template <typename T> 63 class BenchmarkT : public Benchmark { 64 public: BenchmarkT()65 BenchmarkT() {} ~BenchmarkT()66 virtual ~BenchmarkT() {} 67 68 protected: 69 bool ShouldRun(std::vector<regex_t*>&, T arg); 70 void RunWithArg(T arg); 71 virtual void RunIterations(int, T) = 0; 72 virtual std::string GetNameStr(T) = 0; 73 }; 74 75 class BenchmarkWithoutArg : public BenchmarkT<void*> { 76 public: BenchmarkWithoutArg()77 BenchmarkWithoutArg() {} ~BenchmarkWithoutArg()78 virtual ~BenchmarkWithoutArg() {} 79 80 protected: RunAllArgs(std::vector<regex_t * > & regs)81 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; 89 } 90 RunIterations(int iters,void *)91 virtual void RunIterations(int iters, void*) override { 92 Run(iters); 93 } 94 95 virtual void Run(int) = 0; 96 NameColumnWidth()97 virtual size_t NameColumnWidth() override { 98 return Name().size(); 99 } 100 101 virtual std::string GetNameStr(void *) override; 102 }; 103 104 template<typename T> 105 class BenchmarkWithArg : public BenchmarkT<T> { 106 public: BenchmarkWithArg()107 BenchmarkWithArg() {} ~BenchmarkWithArg()108 virtual ~BenchmarkWithArg() {} 109 Arg(T arg)110 BenchmarkWithArg* Arg(T arg) { 111 args_.push_back(arg); 112 return this; 113 } 114 115 protected: NameColumnWidth()116 virtual size_t NameColumnWidth() override { 117 size_t max = 0; 118 for (const auto& arg : args_) { 119 max = std::max(max, GetNameStr(arg).size()); 120 } 121 return max; 122 } 123 124 std::string GetNameStr(T arg) override; 125 RunAllArgs(std::vector<regex_t * > & regs)126 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 } 134 } 135 return benchmarks_run; 136 } 137 RunIterations(int iters,T arg)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 144 private: 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_ 170