xref: /aosp_15_r20/external/libcxx/utils/google-benchmark/src/benchmark_register.cc (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1*58b9f456SAndroid Build Coastguard Worker // Copyright 2015 Google Inc. All rights reserved.
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*58b9f456SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*58b9f456SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*58b9f456SAndroid Build Coastguard Worker //
7*58b9f456SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*58b9f456SAndroid Build Coastguard Worker //
9*58b9f456SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*58b9f456SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*58b9f456SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*58b9f456SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*58b9f456SAndroid Build Coastguard Worker // limitations under the License.
14*58b9f456SAndroid Build Coastguard Worker 
15*58b9f456SAndroid Build Coastguard Worker #include "benchmark_register.h"
16*58b9f456SAndroid Build Coastguard Worker 
17*58b9f456SAndroid Build Coastguard Worker #ifndef BENCHMARK_OS_WINDOWS
18*58b9f456SAndroid Build Coastguard Worker #ifndef BENCHMARK_OS_FUCHSIA
19*58b9f456SAndroid Build Coastguard Worker #include <sys/resource.h>
20*58b9f456SAndroid Build Coastguard Worker #endif
21*58b9f456SAndroid Build Coastguard Worker #include <sys/time.h>
22*58b9f456SAndroid Build Coastguard Worker #include <unistd.h>
23*58b9f456SAndroid Build Coastguard Worker #endif
24*58b9f456SAndroid Build Coastguard Worker 
25*58b9f456SAndroid Build Coastguard Worker #include <algorithm>
26*58b9f456SAndroid Build Coastguard Worker #include <atomic>
27*58b9f456SAndroid Build Coastguard Worker #include <condition_variable>
28*58b9f456SAndroid Build Coastguard Worker #include <cstdio>
29*58b9f456SAndroid Build Coastguard Worker #include <cstdlib>
30*58b9f456SAndroid Build Coastguard Worker #include <cstring>
31*58b9f456SAndroid Build Coastguard Worker #include <fstream>
32*58b9f456SAndroid Build Coastguard Worker #include <iostream>
33*58b9f456SAndroid Build Coastguard Worker #include <memory>
34*58b9f456SAndroid Build Coastguard Worker #include <sstream>
35*58b9f456SAndroid Build Coastguard Worker #include <thread>
36*58b9f456SAndroid Build Coastguard Worker 
37*58b9f456SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
38*58b9f456SAndroid Build Coastguard Worker #include "benchmark_api_internal.h"
39*58b9f456SAndroid Build Coastguard Worker #include "check.h"
40*58b9f456SAndroid Build Coastguard Worker #include "commandlineflags.h"
41*58b9f456SAndroid Build Coastguard Worker #include "complexity.h"
42*58b9f456SAndroid Build Coastguard Worker #include "internal_macros.h"
43*58b9f456SAndroid Build Coastguard Worker #include "log.h"
44*58b9f456SAndroid Build Coastguard Worker #include "mutex.h"
45*58b9f456SAndroid Build Coastguard Worker #include "re.h"
46*58b9f456SAndroid Build Coastguard Worker #include "statistics.h"
47*58b9f456SAndroid Build Coastguard Worker #include "string_util.h"
48*58b9f456SAndroid Build Coastguard Worker #include "timers.h"
49*58b9f456SAndroid Build Coastguard Worker 
50*58b9f456SAndroid Build Coastguard Worker namespace benchmark {
51*58b9f456SAndroid Build Coastguard Worker 
52*58b9f456SAndroid Build Coastguard Worker namespace {
53*58b9f456SAndroid Build Coastguard Worker // For non-dense Range, intermediate values are powers of kRangeMultiplier.
54*58b9f456SAndroid Build Coastguard Worker static const int kRangeMultiplier = 8;
55*58b9f456SAndroid Build Coastguard Worker // The size of a benchmark family determines is the number of inputs to repeat
56*58b9f456SAndroid Build Coastguard Worker // the benchmark on. If this is "large" then warn the user during configuration.
57*58b9f456SAndroid Build Coastguard Worker static const size_t kMaxFamilySize = 100;
58*58b9f456SAndroid Build Coastguard Worker }  // end namespace
59*58b9f456SAndroid Build Coastguard Worker 
60*58b9f456SAndroid Build Coastguard Worker namespace internal {
61*58b9f456SAndroid Build Coastguard Worker 
62*58b9f456SAndroid Build Coastguard Worker //=============================================================================//
63*58b9f456SAndroid Build Coastguard Worker //                         BenchmarkFamilies
64*58b9f456SAndroid Build Coastguard Worker //=============================================================================//
65*58b9f456SAndroid Build Coastguard Worker 
66*58b9f456SAndroid Build Coastguard Worker // Class for managing registered benchmarks.  Note that each registered
67*58b9f456SAndroid Build Coastguard Worker // benchmark identifies a family of related benchmarks to run.
68*58b9f456SAndroid Build Coastguard Worker class BenchmarkFamilies {
69*58b9f456SAndroid Build Coastguard Worker  public:
70*58b9f456SAndroid Build Coastguard Worker   static BenchmarkFamilies* GetInstance();
71*58b9f456SAndroid Build Coastguard Worker 
72*58b9f456SAndroid Build Coastguard Worker   // Registers a benchmark family and returns the index assigned to it.
73*58b9f456SAndroid Build Coastguard Worker   size_t AddBenchmark(std::unique_ptr<Benchmark> family);
74*58b9f456SAndroid Build Coastguard Worker 
75*58b9f456SAndroid Build Coastguard Worker   // Clear all registered benchmark families.
76*58b9f456SAndroid Build Coastguard Worker   void ClearBenchmarks();
77*58b9f456SAndroid Build Coastguard Worker 
78*58b9f456SAndroid Build Coastguard Worker   // Extract the list of benchmark instances that match the specified
79*58b9f456SAndroid Build Coastguard Worker   // regular expression.
80*58b9f456SAndroid Build Coastguard Worker   bool FindBenchmarks(std::string re,
81*58b9f456SAndroid Build Coastguard Worker                       std::vector<BenchmarkInstance>* benchmarks,
82*58b9f456SAndroid Build Coastguard Worker                       std::ostream* Err);
83*58b9f456SAndroid Build Coastguard Worker 
84*58b9f456SAndroid Build Coastguard Worker  private:
BenchmarkFamilies()85*58b9f456SAndroid Build Coastguard Worker   BenchmarkFamilies() {}
86*58b9f456SAndroid Build Coastguard Worker 
87*58b9f456SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<Benchmark>> families_;
88*58b9f456SAndroid Build Coastguard Worker   Mutex mutex_;
89*58b9f456SAndroid Build Coastguard Worker };
90*58b9f456SAndroid Build Coastguard Worker 
GetInstance()91*58b9f456SAndroid Build Coastguard Worker BenchmarkFamilies* BenchmarkFamilies::GetInstance() {
92*58b9f456SAndroid Build Coastguard Worker   static BenchmarkFamilies instance;
93*58b9f456SAndroid Build Coastguard Worker   return &instance;
94*58b9f456SAndroid Build Coastguard Worker }
95*58b9f456SAndroid Build Coastguard Worker 
AddBenchmark(std::unique_ptr<Benchmark> family)96*58b9f456SAndroid Build Coastguard Worker size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr<Benchmark> family) {
97*58b9f456SAndroid Build Coastguard Worker   MutexLock l(mutex_);
98*58b9f456SAndroid Build Coastguard Worker   size_t index = families_.size();
99*58b9f456SAndroid Build Coastguard Worker   families_.push_back(std::move(family));
100*58b9f456SAndroid Build Coastguard Worker   return index;
101*58b9f456SAndroid Build Coastguard Worker }
102*58b9f456SAndroid Build Coastguard Worker 
ClearBenchmarks()103*58b9f456SAndroid Build Coastguard Worker void BenchmarkFamilies::ClearBenchmarks() {
104*58b9f456SAndroid Build Coastguard Worker   MutexLock l(mutex_);
105*58b9f456SAndroid Build Coastguard Worker   families_.clear();
106*58b9f456SAndroid Build Coastguard Worker   families_.shrink_to_fit();
107*58b9f456SAndroid Build Coastguard Worker }
108*58b9f456SAndroid Build Coastguard Worker 
FindBenchmarks(std::string spec,std::vector<BenchmarkInstance> * benchmarks,std::ostream * ErrStream)109*58b9f456SAndroid Build Coastguard Worker bool BenchmarkFamilies::FindBenchmarks(
110*58b9f456SAndroid Build Coastguard Worker     std::string spec, std::vector<BenchmarkInstance>* benchmarks,
111*58b9f456SAndroid Build Coastguard Worker     std::ostream* ErrStream) {
112*58b9f456SAndroid Build Coastguard Worker   CHECK(ErrStream);
113*58b9f456SAndroid Build Coastguard Worker   auto& Err = *ErrStream;
114*58b9f456SAndroid Build Coastguard Worker   // Make regular expression out of command-line flag
115*58b9f456SAndroid Build Coastguard Worker   std::string error_msg;
116*58b9f456SAndroid Build Coastguard Worker   Regex re;
117*58b9f456SAndroid Build Coastguard Worker   bool isNegativeFilter = false;
118*58b9f456SAndroid Build Coastguard Worker   if (spec[0] == '-') {
119*58b9f456SAndroid Build Coastguard Worker     spec.replace(0, 1, "");
120*58b9f456SAndroid Build Coastguard Worker     isNegativeFilter = true;
121*58b9f456SAndroid Build Coastguard Worker   }
122*58b9f456SAndroid Build Coastguard Worker   if (!re.Init(spec, &error_msg)) {
123*58b9f456SAndroid Build Coastguard Worker     Err << "Could not compile benchmark re: " << error_msg << std::endl;
124*58b9f456SAndroid Build Coastguard Worker     return false;
125*58b9f456SAndroid Build Coastguard Worker   }
126*58b9f456SAndroid Build Coastguard Worker 
127*58b9f456SAndroid Build Coastguard Worker   // Special list of thread counts to use when none are specified
128*58b9f456SAndroid Build Coastguard Worker   const std::vector<int> one_thread = {1};
129*58b9f456SAndroid Build Coastguard Worker 
130*58b9f456SAndroid Build Coastguard Worker   MutexLock l(mutex_);
131*58b9f456SAndroid Build Coastguard Worker   for (std::unique_ptr<Benchmark>& family : families_) {
132*58b9f456SAndroid Build Coastguard Worker     // Family was deleted or benchmark doesn't match
133*58b9f456SAndroid Build Coastguard Worker     if (!family) continue;
134*58b9f456SAndroid Build Coastguard Worker 
135*58b9f456SAndroid Build Coastguard Worker     if (family->ArgsCnt() == -1) {
136*58b9f456SAndroid Build Coastguard Worker       family->Args({});
137*58b9f456SAndroid Build Coastguard Worker     }
138*58b9f456SAndroid Build Coastguard Worker     const std::vector<int>* thread_counts =
139*58b9f456SAndroid Build Coastguard Worker         (family->thread_counts_.empty()
140*58b9f456SAndroid Build Coastguard Worker              ? &one_thread
141*58b9f456SAndroid Build Coastguard Worker              : &static_cast<const std::vector<int>&>(family->thread_counts_));
142*58b9f456SAndroid Build Coastguard Worker     const size_t family_size = family->args_.size() * thread_counts->size();
143*58b9f456SAndroid Build Coastguard Worker     // The benchmark will be run at least 'family_size' different inputs.
144*58b9f456SAndroid Build Coastguard Worker     // If 'family_size' is very large warn the user.
145*58b9f456SAndroid Build Coastguard Worker     if (family_size > kMaxFamilySize) {
146*58b9f456SAndroid Build Coastguard Worker       Err << "The number of inputs is very large. " << family->name_
147*58b9f456SAndroid Build Coastguard Worker           << " will be repeated at least " << family_size << " times.\n";
148*58b9f456SAndroid Build Coastguard Worker     }
149*58b9f456SAndroid Build Coastguard Worker     // reserve in the special case the regex ".", since we know the final
150*58b9f456SAndroid Build Coastguard Worker     // family size.
151*58b9f456SAndroid Build Coastguard Worker     if (spec == ".") benchmarks->reserve(family_size);
152*58b9f456SAndroid Build Coastguard Worker 
153*58b9f456SAndroid Build Coastguard Worker     for (auto const& args : family->args_) {
154*58b9f456SAndroid Build Coastguard Worker       for (int num_threads : *thread_counts) {
155*58b9f456SAndroid Build Coastguard Worker         BenchmarkInstance instance;
156*58b9f456SAndroid Build Coastguard Worker         instance.name = family->name_;
157*58b9f456SAndroid Build Coastguard Worker         instance.benchmark = family.get();
158*58b9f456SAndroid Build Coastguard Worker         instance.aggregation_report_mode = family->aggregation_report_mode_;
159*58b9f456SAndroid Build Coastguard Worker         instance.arg = args;
160*58b9f456SAndroid Build Coastguard Worker         instance.time_unit = family->time_unit_;
161*58b9f456SAndroid Build Coastguard Worker         instance.range_multiplier = family->range_multiplier_;
162*58b9f456SAndroid Build Coastguard Worker         instance.min_time = family->min_time_;
163*58b9f456SAndroid Build Coastguard Worker         instance.iterations = family->iterations_;
164*58b9f456SAndroid Build Coastguard Worker         instance.repetitions = family->repetitions_;
165*58b9f456SAndroid Build Coastguard Worker         instance.use_real_time = family->use_real_time_;
166*58b9f456SAndroid Build Coastguard Worker         instance.use_manual_time = family->use_manual_time_;
167*58b9f456SAndroid Build Coastguard Worker         instance.complexity = family->complexity_;
168*58b9f456SAndroid Build Coastguard Worker         instance.complexity_lambda = family->complexity_lambda_;
169*58b9f456SAndroid Build Coastguard Worker         instance.statistics = &family->statistics_;
170*58b9f456SAndroid Build Coastguard Worker         instance.threads = num_threads;
171*58b9f456SAndroid Build Coastguard Worker 
172*58b9f456SAndroid Build Coastguard Worker         // Add arguments to instance name
173*58b9f456SAndroid Build Coastguard Worker         size_t arg_i = 0;
174*58b9f456SAndroid Build Coastguard Worker         for (auto const& arg : args) {
175*58b9f456SAndroid Build Coastguard Worker           instance.name += "/";
176*58b9f456SAndroid Build Coastguard Worker 
177*58b9f456SAndroid Build Coastguard Worker           if (arg_i < family->arg_names_.size()) {
178*58b9f456SAndroid Build Coastguard Worker             const auto& arg_name = family->arg_names_[arg_i];
179*58b9f456SAndroid Build Coastguard Worker             if (!arg_name.empty()) {
180*58b9f456SAndroid Build Coastguard Worker               instance.name +=
181*58b9f456SAndroid Build Coastguard Worker                   StrFormat("%s:", family->arg_names_[arg_i].c_str());
182*58b9f456SAndroid Build Coastguard Worker             }
183*58b9f456SAndroid Build Coastguard Worker           }
184*58b9f456SAndroid Build Coastguard Worker 
185*58b9f456SAndroid Build Coastguard Worker           // we know that the args are always non-negative (see 'AddRange()'),
186*58b9f456SAndroid Build Coastguard Worker           // thus print as 'unsigned'. BUT, do a cast due to the 32-bit builds.
187*58b9f456SAndroid Build Coastguard Worker           instance.name += StrFormat("%lu", static_cast<unsigned long>(arg));
188*58b9f456SAndroid Build Coastguard Worker           ++arg_i;
189*58b9f456SAndroid Build Coastguard Worker         }
190*58b9f456SAndroid Build Coastguard Worker 
191*58b9f456SAndroid Build Coastguard Worker         if (!IsZero(family->min_time_))
192*58b9f456SAndroid Build Coastguard Worker           instance.name += StrFormat("/min_time:%0.3f", family->min_time_);
193*58b9f456SAndroid Build Coastguard Worker         if (family->iterations_ != 0) {
194*58b9f456SAndroid Build Coastguard Worker           instance.name +=
195*58b9f456SAndroid Build Coastguard Worker               StrFormat("/iterations:%lu",
196*58b9f456SAndroid Build Coastguard Worker                         static_cast<unsigned long>(family->iterations_));
197*58b9f456SAndroid Build Coastguard Worker         }
198*58b9f456SAndroid Build Coastguard Worker         if (family->repetitions_ != 0)
199*58b9f456SAndroid Build Coastguard Worker           instance.name += StrFormat("/repeats:%d", family->repetitions_);
200*58b9f456SAndroid Build Coastguard Worker 
201*58b9f456SAndroid Build Coastguard Worker         if (family->use_manual_time_) {
202*58b9f456SAndroid Build Coastguard Worker           instance.name += "/manual_time";
203*58b9f456SAndroid Build Coastguard Worker         } else if (family->use_real_time_) {
204*58b9f456SAndroid Build Coastguard Worker           instance.name += "/real_time";
205*58b9f456SAndroid Build Coastguard Worker         }
206*58b9f456SAndroid Build Coastguard Worker 
207*58b9f456SAndroid Build Coastguard Worker         // Add the number of threads used to the name
208*58b9f456SAndroid Build Coastguard Worker         if (!family->thread_counts_.empty()) {
209*58b9f456SAndroid Build Coastguard Worker           instance.name += StrFormat("/threads:%d", instance.threads);
210*58b9f456SAndroid Build Coastguard Worker         }
211*58b9f456SAndroid Build Coastguard Worker 
212*58b9f456SAndroid Build Coastguard Worker         if ((re.Match(instance.name) && !isNegativeFilter) ||
213*58b9f456SAndroid Build Coastguard Worker             (!re.Match(instance.name) && isNegativeFilter)) {
214*58b9f456SAndroid Build Coastguard Worker           instance.last_benchmark_instance = (&args == &family->args_.back());
215*58b9f456SAndroid Build Coastguard Worker           benchmarks->push_back(std::move(instance));
216*58b9f456SAndroid Build Coastguard Worker         }
217*58b9f456SAndroid Build Coastguard Worker       }
218*58b9f456SAndroid Build Coastguard Worker     }
219*58b9f456SAndroid Build Coastguard Worker   }
220*58b9f456SAndroid Build Coastguard Worker   return true;
221*58b9f456SAndroid Build Coastguard Worker }
222*58b9f456SAndroid Build Coastguard Worker 
RegisterBenchmarkInternal(Benchmark * bench)223*58b9f456SAndroid Build Coastguard Worker Benchmark* RegisterBenchmarkInternal(Benchmark* bench) {
224*58b9f456SAndroid Build Coastguard Worker   std::unique_ptr<Benchmark> bench_ptr(bench);
225*58b9f456SAndroid Build Coastguard Worker   BenchmarkFamilies* families = BenchmarkFamilies::GetInstance();
226*58b9f456SAndroid Build Coastguard Worker   families->AddBenchmark(std::move(bench_ptr));
227*58b9f456SAndroid Build Coastguard Worker   return bench;
228*58b9f456SAndroid Build Coastguard Worker }
229*58b9f456SAndroid Build Coastguard Worker 
230*58b9f456SAndroid Build Coastguard Worker // FIXME: This function is a hack so that benchmark.cc can access
231*58b9f456SAndroid Build Coastguard Worker // `BenchmarkFamilies`
FindBenchmarksInternal(const std::string & re,std::vector<BenchmarkInstance> * benchmarks,std::ostream * Err)232*58b9f456SAndroid Build Coastguard Worker bool FindBenchmarksInternal(const std::string& re,
233*58b9f456SAndroid Build Coastguard Worker                             std::vector<BenchmarkInstance>* benchmarks,
234*58b9f456SAndroid Build Coastguard Worker                             std::ostream* Err) {
235*58b9f456SAndroid Build Coastguard Worker   return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err);
236*58b9f456SAndroid Build Coastguard Worker }
237*58b9f456SAndroid Build Coastguard Worker 
238*58b9f456SAndroid Build Coastguard Worker //=============================================================================//
239*58b9f456SAndroid Build Coastguard Worker //                               Benchmark
240*58b9f456SAndroid Build Coastguard Worker //=============================================================================//
241*58b9f456SAndroid Build Coastguard Worker 
Benchmark(const char * name)242*58b9f456SAndroid Build Coastguard Worker Benchmark::Benchmark(const char* name)
243*58b9f456SAndroid Build Coastguard Worker     : name_(name),
244*58b9f456SAndroid Build Coastguard Worker       aggregation_report_mode_(ARM_Unspecified),
245*58b9f456SAndroid Build Coastguard Worker       time_unit_(kNanosecond),
246*58b9f456SAndroid Build Coastguard Worker       range_multiplier_(kRangeMultiplier),
247*58b9f456SAndroid Build Coastguard Worker       min_time_(0),
248*58b9f456SAndroid Build Coastguard Worker       iterations_(0),
249*58b9f456SAndroid Build Coastguard Worker       repetitions_(0),
250*58b9f456SAndroid Build Coastguard Worker       use_real_time_(false),
251*58b9f456SAndroid Build Coastguard Worker       use_manual_time_(false),
252*58b9f456SAndroid Build Coastguard Worker       complexity_(oNone),
253*58b9f456SAndroid Build Coastguard Worker       complexity_lambda_(nullptr) {
254*58b9f456SAndroid Build Coastguard Worker   ComputeStatistics("mean", StatisticsMean);
255*58b9f456SAndroid Build Coastguard Worker   ComputeStatistics("median", StatisticsMedian);
256*58b9f456SAndroid Build Coastguard Worker   ComputeStatistics("stddev", StatisticsStdDev);
257*58b9f456SAndroid Build Coastguard Worker }
258*58b9f456SAndroid Build Coastguard Worker 
~Benchmark()259*58b9f456SAndroid Build Coastguard Worker Benchmark::~Benchmark() {}
260*58b9f456SAndroid Build Coastguard Worker 
Arg(int64_t x)261*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Arg(int64_t x) {
262*58b9f456SAndroid Build Coastguard Worker   CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
263*58b9f456SAndroid Build Coastguard Worker   args_.push_back({x});
264*58b9f456SAndroid Build Coastguard Worker   return this;
265*58b9f456SAndroid Build Coastguard Worker }
266*58b9f456SAndroid Build Coastguard Worker 
Unit(TimeUnit unit)267*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Unit(TimeUnit unit) {
268*58b9f456SAndroid Build Coastguard Worker   time_unit_ = unit;
269*58b9f456SAndroid Build Coastguard Worker   return this;
270*58b9f456SAndroid Build Coastguard Worker }
271*58b9f456SAndroid Build Coastguard Worker 
Range(int64_t start,int64_t limit)272*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Range(int64_t start, int64_t limit) {
273*58b9f456SAndroid Build Coastguard Worker   CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
274*58b9f456SAndroid Build Coastguard Worker   std::vector<int64_t> arglist;
275*58b9f456SAndroid Build Coastguard Worker   AddRange(&arglist, start, limit, range_multiplier_);
276*58b9f456SAndroid Build Coastguard Worker 
277*58b9f456SAndroid Build Coastguard Worker   for (int64_t i : arglist) {
278*58b9f456SAndroid Build Coastguard Worker     args_.push_back({i});
279*58b9f456SAndroid Build Coastguard Worker   }
280*58b9f456SAndroid Build Coastguard Worker   return this;
281*58b9f456SAndroid Build Coastguard Worker }
282*58b9f456SAndroid Build Coastguard Worker 
Ranges(const std::vector<std::pair<int64_t,int64_t>> & ranges)283*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Ranges(
284*58b9f456SAndroid Build Coastguard Worker     const std::vector<std::pair<int64_t, int64_t>>& ranges) {
285*58b9f456SAndroid Build Coastguard Worker   CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size()));
286*58b9f456SAndroid Build Coastguard Worker   std::vector<std::vector<int64_t>> arglists(ranges.size());
287*58b9f456SAndroid Build Coastguard Worker   std::size_t total = 1;
288*58b9f456SAndroid Build Coastguard Worker   for (std::size_t i = 0; i < ranges.size(); i++) {
289*58b9f456SAndroid Build Coastguard Worker     AddRange(&arglists[i], ranges[i].first, ranges[i].second,
290*58b9f456SAndroid Build Coastguard Worker              range_multiplier_);
291*58b9f456SAndroid Build Coastguard Worker     total *= arglists[i].size();
292*58b9f456SAndroid Build Coastguard Worker   }
293*58b9f456SAndroid Build Coastguard Worker 
294*58b9f456SAndroid Build Coastguard Worker   std::vector<std::size_t> ctr(arglists.size(), 0);
295*58b9f456SAndroid Build Coastguard Worker 
296*58b9f456SAndroid Build Coastguard Worker   for (std::size_t i = 0; i < total; i++) {
297*58b9f456SAndroid Build Coastguard Worker     std::vector<int64_t> tmp;
298*58b9f456SAndroid Build Coastguard Worker     tmp.reserve(arglists.size());
299*58b9f456SAndroid Build Coastguard Worker 
300*58b9f456SAndroid Build Coastguard Worker     for (std::size_t j = 0; j < arglists.size(); j++) {
301*58b9f456SAndroid Build Coastguard Worker       tmp.push_back(arglists[j].at(ctr[j]));
302*58b9f456SAndroid Build Coastguard Worker     }
303*58b9f456SAndroid Build Coastguard Worker 
304*58b9f456SAndroid Build Coastguard Worker     args_.push_back(std::move(tmp));
305*58b9f456SAndroid Build Coastguard Worker 
306*58b9f456SAndroid Build Coastguard Worker     for (std::size_t j = 0; j < arglists.size(); j++) {
307*58b9f456SAndroid Build Coastguard Worker       if (ctr[j] + 1 < arglists[j].size()) {
308*58b9f456SAndroid Build Coastguard Worker         ++ctr[j];
309*58b9f456SAndroid Build Coastguard Worker         break;
310*58b9f456SAndroid Build Coastguard Worker       }
311*58b9f456SAndroid Build Coastguard Worker       ctr[j] = 0;
312*58b9f456SAndroid Build Coastguard Worker     }
313*58b9f456SAndroid Build Coastguard Worker   }
314*58b9f456SAndroid Build Coastguard Worker   return this;
315*58b9f456SAndroid Build Coastguard Worker }
316*58b9f456SAndroid Build Coastguard Worker 
ArgName(const std::string & name)317*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::ArgName(const std::string& name) {
318*58b9f456SAndroid Build Coastguard Worker   CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
319*58b9f456SAndroid Build Coastguard Worker   arg_names_ = {name};
320*58b9f456SAndroid Build Coastguard Worker   return this;
321*58b9f456SAndroid Build Coastguard Worker }
322*58b9f456SAndroid Build Coastguard Worker 
ArgNames(const std::vector<std::string> & names)323*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::ArgNames(const std::vector<std::string>& names) {
324*58b9f456SAndroid Build Coastguard Worker   CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(names.size()));
325*58b9f456SAndroid Build Coastguard Worker   arg_names_ = names;
326*58b9f456SAndroid Build Coastguard Worker   return this;
327*58b9f456SAndroid Build Coastguard Worker }
328*58b9f456SAndroid Build Coastguard Worker 
DenseRange(int64_t start,int64_t limit,int step)329*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::DenseRange(int64_t start, int64_t limit, int step) {
330*58b9f456SAndroid Build Coastguard Worker   CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
331*58b9f456SAndroid Build Coastguard Worker   CHECK_GE(start, 0);
332*58b9f456SAndroid Build Coastguard Worker   CHECK_LE(start, limit);
333*58b9f456SAndroid Build Coastguard Worker   for (int64_t arg = start; arg <= limit; arg += step) {
334*58b9f456SAndroid Build Coastguard Worker     args_.push_back({arg});
335*58b9f456SAndroid Build Coastguard Worker   }
336*58b9f456SAndroid Build Coastguard Worker   return this;
337*58b9f456SAndroid Build Coastguard Worker }
338*58b9f456SAndroid Build Coastguard Worker 
Args(const std::vector<int64_t> & args)339*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Args(const std::vector<int64_t>& args) {
340*58b9f456SAndroid Build Coastguard Worker   CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(args.size()));
341*58b9f456SAndroid Build Coastguard Worker   args_.push_back(args);
342*58b9f456SAndroid Build Coastguard Worker   return this;
343*58b9f456SAndroid Build Coastguard Worker }
344*58b9f456SAndroid Build Coastguard Worker 
Apply(void (* custom_arguments)(Benchmark * benchmark))345*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) {
346*58b9f456SAndroid Build Coastguard Worker   custom_arguments(this);
347*58b9f456SAndroid Build Coastguard Worker   return this;
348*58b9f456SAndroid Build Coastguard Worker }
349*58b9f456SAndroid Build Coastguard Worker 
RangeMultiplier(int multiplier)350*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::RangeMultiplier(int multiplier) {
351*58b9f456SAndroid Build Coastguard Worker   CHECK(multiplier > 1);
352*58b9f456SAndroid Build Coastguard Worker   range_multiplier_ = multiplier;
353*58b9f456SAndroid Build Coastguard Worker   return this;
354*58b9f456SAndroid Build Coastguard Worker }
355*58b9f456SAndroid Build Coastguard Worker 
MinTime(double t)356*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::MinTime(double t) {
357*58b9f456SAndroid Build Coastguard Worker   CHECK(t > 0.0);
358*58b9f456SAndroid Build Coastguard Worker   CHECK(iterations_ == 0);
359*58b9f456SAndroid Build Coastguard Worker   min_time_ = t;
360*58b9f456SAndroid Build Coastguard Worker   return this;
361*58b9f456SAndroid Build Coastguard Worker }
362*58b9f456SAndroid Build Coastguard Worker 
Iterations(size_t n)363*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Iterations(size_t n) {
364*58b9f456SAndroid Build Coastguard Worker   CHECK(n > 0);
365*58b9f456SAndroid Build Coastguard Worker   CHECK(IsZero(min_time_));
366*58b9f456SAndroid Build Coastguard Worker   iterations_ = n;
367*58b9f456SAndroid Build Coastguard Worker   return this;
368*58b9f456SAndroid Build Coastguard Worker }
369*58b9f456SAndroid Build Coastguard Worker 
Repetitions(int n)370*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Repetitions(int n) {
371*58b9f456SAndroid Build Coastguard Worker   CHECK(n > 0);
372*58b9f456SAndroid Build Coastguard Worker   repetitions_ = n;
373*58b9f456SAndroid Build Coastguard Worker   return this;
374*58b9f456SAndroid Build Coastguard Worker }
375*58b9f456SAndroid Build Coastguard Worker 
ReportAggregatesOnly(bool value)376*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::ReportAggregatesOnly(bool value) {
377*58b9f456SAndroid Build Coastguard Worker   aggregation_report_mode_ = value ? ARM_ReportAggregatesOnly : ARM_Default;
378*58b9f456SAndroid Build Coastguard Worker   return this;
379*58b9f456SAndroid Build Coastguard Worker }
380*58b9f456SAndroid Build Coastguard Worker 
DisplayAggregatesOnly(bool value)381*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::DisplayAggregatesOnly(bool value) {
382*58b9f456SAndroid Build Coastguard Worker   // If we were called, the report mode is no longer 'unspecified', in any case.
383*58b9f456SAndroid Build Coastguard Worker   aggregation_report_mode_ = static_cast<AggregationReportMode>(
384*58b9f456SAndroid Build Coastguard Worker       aggregation_report_mode_ | ARM_Default);
385*58b9f456SAndroid Build Coastguard Worker 
386*58b9f456SAndroid Build Coastguard Worker   if (value) {
387*58b9f456SAndroid Build Coastguard Worker     aggregation_report_mode_ = static_cast<AggregationReportMode>(
388*58b9f456SAndroid Build Coastguard Worker         aggregation_report_mode_ | ARM_DisplayReportAggregatesOnly);
389*58b9f456SAndroid Build Coastguard Worker   } else {
390*58b9f456SAndroid Build Coastguard Worker     aggregation_report_mode_ = static_cast<AggregationReportMode>(
391*58b9f456SAndroid Build Coastguard Worker         aggregation_report_mode_ & ~ARM_DisplayReportAggregatesOnly);
392*58b9f456SAndroid Build Coastguard Worker   }
393*58b9f456SAndroid Build Coastguard Worker 
394*58b9f456SAndroid Build Coastguard Worker   return this;
395*58b9f456SAndroid Build Coastguard Worker }
396*58b9f456SAndroid Build Coastguard Worker 
UseRealTime()397*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::UseRealTime() {
398*58b9f456SAndroid Build Coastguard Worker   CHECK(!use_manual_time_)
399*58b9f456SAndroid Build Coastguard Worker       << "Cannot set UseRealTime and UseManualTime simultaneously.";
400*58b9f456SAndroid Build Coastguard Worker   use_real_time_ = true;
401*58b9f456SAndroid Build Coastguard Worker   return this;
402*58b9f456SAndroid Build Coastguard Worker }
403*58b9f456SAndroid Build Coastguard Worker 
UseManualTime()404*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::UseManualTime() {
405*58b9f456SAndroid Build Coastguard Worker   CHECK(!use_real_time_)
406*58b9f456SAndroid Build Coastguard Worker       << "Cannot set UseRealTime and UseManualTime simultaneously.";
407*58b9f456SAndroid Build Coastguard Worker   use_manual_time_ = true;
408*58b9f456SAndroid Build Coastguard Worker   return this;
409*58b9f456SAndroid Build Coastguard Worker }
410*58b9f456SAndroid Build Coastguard Worker 
Complexity(BigO complexity)411*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Complexity(BigO complexity) {
412*58b9f456SAndroid Build Coastguard Worker   complexity_ = complexity;
413*58b9f456SAndroid Build Coastguard Worker   return this;
414*58b9f456SAndroid Build Coastguard Worker }
415*58b9f456SAndroid Build Coastguard Worker 
Complexity(BigOFunc * complexity)416*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Complexity(BigOFunc* complexity) {
417*58b9f456SAndroid Build Coastguard Worker   complexity_lambda_ = complexity;
418*58b9f456SAndroid Build Coastguard Worker   complexity_ = oLambda;
419*58b9f456SAndroid Build Coastguard Worker   return this;
420*58b9f456SAndroid Build Coastguard Worker }
421*58b9f456SAndroid Build Coastguard Worker 
ComputeStatistics(std::string name,StatisticsFunc * statistics)422*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::ComputeStatistics(std::string name,
423*58b9f456SAndroid Build Coastguard Worker                                         StatisticsFunc* statistics) {
424*58b9f456SAndroid Build Coastguard Worker   statistics_.emplace_back(name, statistics);
425*58b9f456SAndroid Build Coastguard Worker   return this;
426*58b9f456SAndroid Build Coastguard Worker }
427*58b9f456SAndroid Build Coastguard Worker 
Threads(int t)428*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::Threads(int t) {
429*58b9f456SAndroid Build Coastguard Worker   CHECK_GT(t, 0);
430*58b9f456SAndroid Build Coastguard Worker   thread_counts_.push_back(t);
431*58b9f456SAndroid Build Coastguard Worker   return this;
432*58b9f456SAndroid Build Coastguard Worker }
433*58b9f456SAndroid Build Coastguard Worker 
ThreadRange(int min_threads,int max_threads)434*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
435*58b9f456SAndroid Build Coastguard Worker   CHECK_GT(min_threads, 0);
436*58b9f456SAndroid Build Coastguard Worker   CHECK_GE(max_threads, min_threads);
437*58b9f456SAndroid Build Coastguard Worker 
438*58b9f456SAndroid Build Coastguard Worker   AddRange(&thread_counts_, min_threads, max_threads, 2);
439*58b9f456SAndroid Build Coastguard Worker   return this;
440*58b9f456SAndroid Build Coastguard Worker }
441*58b9f456SAndroid Build Coastguard Worker 
DenseThreadRange(int min_threads,int max_threads,int stride)442*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::DenseThreadRange(int min_threads, int max_threads,
443*58b9f456SAndroid Build Coastguard Worker                                        int stride) {
444*58b9f456SAndroid Build Coastguard Worker   CHECK_GT(min_threads, 0);
445*58b9f456SAndroid Build Coastguard Worker   CHECK_GE(max_threads, min_threads);
446*58b9f456SAndroid Build Coastguard Worker   CHECK_GE(stride, 1);
447*58b9f456SAndroid Build Coastguard Worker 
448*58b9f456SAndroid Build Coastguard Worker   for (auto i = min_threads; i < max_threads; i += stride) {
449*58b9f456SAndroid Build Coastguard Worker     thread_counts_.push_back(i);
450*58b9f456SAndroid Build Coastguard Worker   }
451*58b9f456SAndroid Build Coastguard Worker   thread_counts_.push_back(max_threads);
452*58b9f456SAndroid Build Coastguard Worker   return this;
453*58b9f456SAndroid Build Coastguard Worker }
454*58b9f456SAndroid Build Coastguard Worker 
ThreadPerCpu()455*58b9f456SAndroid Build Coastguard Worker Benchmark* Benchmark::ThreadPerCpu() {
456*58b9f456SAndroid Build Coastguard Worker   thread_counts_.push_back(CPUInfo::Get().num_cpus);
457*58b9f456SAndroid Build Coastguard Worker   return this;
458*58b9f456SAndroid Build Coastguard Worker }
459*58b9f456SAndroid Build Coastguard Worker 
SetName(const char * name)460*58b9f456SAndroid Build Coastguard Worker void Benchmark::SetName(const char* name) { name_ = name; }
461*58b9f456SAndroid Build Coastguard Worker 
ArgsCnt() const462*58b9f456SAndroid Build Coastguard Worker int Benchmark::ArgsCnt() const {
463*58b9f456SAndroid Build Coastguard Worker   if (args_.empty()) {
464*58b9f456SAndroid Build Coastguard Worker     if (arg_names_.empty()) return -1;
465*58b9f456SAndroid Build Coastguard Worker     return static_cast<int>(arg_names_.size());
466*58b9f456SAndroid Build Coastguard Worker   }
467*58b9f456SAndroid Build Coastguard Worker   return static_cast<int>(args_.front().size());
468*58b9f456SAndroid Build Coastguard Worker }
469*58b9f456SAndroid Build Coastguard Worker 
470*58b9f456SAndroid Build Coastguard Worker //=============================================================================//
471*58b9f456SAndroid Build Coastguard Worker //                            FunctionBenchmark
472*58b9f456SAndroid Build Coastguard Worker //=============================================================================//
473*58b9f456SAndroid Build Coastguard Worker 
Run(State & st)474*58b9f456SAndroid Build Coastguard Worker void FunctionBenchmark::Run(State& st) { func_(st); }
475*58b9f456SAndroid Build Coastguard Worker 
476*58b9f456SAndroid Build Coastguard Worker }  // end namespace internal
477*58b9f456SAndroid Build Coastguard Worker 
ClearRegisteredBenchmarks()478*58b9f456SAndroid Build Coastguard Worker void ClearRegisteredBenchmarks() {
479*58b9f456SAndroid Build Coastguard Worker   internal::BenchmarkFamilies::GetInstance()->ClearBenchmarks();
480*58b9f456SAndroid Build Coastguard Worker }
481*58b9f456SAndroid Build Coastguard Worker 
482*58b9f456SAndroid Build Coastguard Worker }  // end namespace benchmark
483