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