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