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