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