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/benchmark.h"
16a8c51b3fSopenharmony_ci
17a8c51b3fSopenharmony_ci#include "benchmark_api_internal.h"
18a8c51b3fSopenharmony_ci#include "benchmark_runner.h"
19a8c51b3fSopenharmony_ci#include "internal_macros.h"
20a8c51b3fSopenharmony_ci
21a8c51b3fSopenharmony_ci#ifndef BENCHMARK_OS_WINDOWS
22a8c51b3fSopenharmony_ci#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
23a8c51b3fSopenharmony_ci#include <sys/resource.h>
24a8c51b3fSopenharmony_ci#endif
25a8c51b3fSopenharmony_ci#include <sys/time.h>
26a8c51b3fSopenharmony_ci#include <unistd.h>
27a8c51b3fSopenharmony_ci#endif
28a8c51b3fSopenharmony_ci
29a8c51b3fSopenharmony_ci#include <algorithm>
30a8c51b3fSopenharmony_ci#include <atomic>
31a8c51b3fSopenharmony_ci#include <condition_variable>
32a8c51b3fSopenharmony_ci#include <cstdio>
33a8c51b3fSopenharmony_ci#include <cstdlib>
34a8c51b3fSopenharmony_ci#include <fstream>
35a8c51b3fSopenharmony_ci#include <iostream>
36a8c51b3fSopenharmony_ci#include <limits>
37a8c51b3fSopenharmony_ci#include <map>
38a8c51b3fSopenharmony_ci#include <memory>
39a8c51b3fSopenharmony_ci#include <random>
40a8c51b3fSopenharmony_ci#include <string>
41a8c51b3fSopenharmony_ci#include <thread>
42a8c51b3fSopenharmony_ci#include <utility>
43a8c51b3fSopenharmony_ci
44a8c51b3fSopenharmony_ci#include "check.h"
45a8c51b3fSopenharmony_ci#include "colorprint.h"
46a8c51b3fSopenharmony_ci#include "commandlineflags.h"
47a8c51b3fSopenharmony_ci#include "complexity.h"
48a8c51b3fSopenharmony_ci#include "counter.h"
49a8c51b3fSopenharmony_ci#include "internal_macros.h"
50a8c51b3fSopenharmony_ci#include "log.h"
51a8c51b3fSopenharmony_ci#include "mutex.h"
52a8c51b3fSopenharmony_ci#include "perf_counters.h"
53a8c51b3fSopenharmony_ci#include "re.h"
54a8c51b3fSopenharmony_ci#include "statistics.h"
55a8c51b3fSopenharmony_ci#include "string_util.h"
56a8c51b3fSopenharmony_ci#include "thread_manager.h"
57a8c51b3fSopenharmony_ci#include "thread_timer.h"
58a8c51b3fSopenharmony_ci
59a8c51b3fSopenharmony_cinamespace benchmark {
60a8c51b3fSopenharmony_ci// Print a list of benchmarks. This option overrides all other options.
61a8c51b3fSopenharmony_ciBM_DEFINE_bool(benchmark_list_tests, false);
62a8c51b3fSopenharmony_ci
63a8c51b3fSopenharmony_ci// A regular expression that specifies the set of benchmarks to execute.  If
64a8c51b3fSopenharmony_ci// this flag is empty, or if this flag is the string \"all\", all benchmarks
65a8c51b3fSopenharmony_ci// linked into the binary are run.
66a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_filter, "");
67a8c51b3fSopenharmony_ci
68a8c51b3fSopenharmony_ci// Specification of how long to run the benchmark.
69a8c51b3fSopenharmony_ci//
70a8c51b3fSopenharmony_ci// It can be either an exact number of iterations (specified as `<integer>x`),
71a8c51b3fSopenharmony_ci// or a minimum number of seconds (specified as `<float>s`). If the latter
72a8c51b3fSopenharmony_ci// format (ie., min seconds) is used, the system may run the benchmark longer
73a8c51b3fSopenharmony_ci// until the results are considered significant.
74a8c51b3fSopenharmony_ci//
75a8c51b3fSopenharmony_ci// For backward compatibility, the `s` suffix may be omitted, in which case,
76a8c51b3fSopenharmony_ci// the specified number is interpreted as the number of seconds.
77a8c51b3fSopenharmony_ci//
78a8c51b3fSopenharmony_ci// For cpu-time based tests, this is the lower bound
79a8c51b3fSopenharmony_ci// on the total cpu time used by all threads that make up the test.  For
80a8c51b3fSopenharmony_ci// real-time based tests, this is the lower bound on the elapsed time of the
81a8c51b3fSopenharmony_ci// benchmark execution, regardless of number of threads.
82a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_min_time, kDefaultMinTimeStr);
83a8c51b3fSopenharmony_ci
84a8c51b3fSopenharmony_ci// Minimum number of seconds a benchmark should be run before results should be
85a8c51b3fSopenharmony_ci// taken into account. This e.g can be necessary for benchmarks of code which
86a8c51b3fSopenharmony_ci// needs to fill some form of cache before performance is of interest.
87a8c51b3fSopenharmony_ci// Note: results gathered within this period are discarded and not used for
88a8c51b3fSopenharmony_ci// reported result.
89a8c51b3fSopenharmony_ciBM_DEFINE_double(benchmark_min_warmup_time, 0.0);
90a8c51b3fSopenharmony_ci
91a8c51b3fSopenharmony_ci// The number of runs of each benchmark. If greater than 1, the mean and
92a8c51b3fSopenharmony_ci// standard deviation of the runs will be reported.
93a8c51b3fSopenharmony_ciBM_DEFINE_int32(benchmark_repetitions, 1);
94a8c51b3fSopenharmony_ci
95a8c51b3fSopenharmony_ci// If set, enable random interleaving of repetitions of all benchmarks.
96a8c51b3fSopenharmony_ci// See http://github.com/google/benchmark/issues/1051 for details.
97a8c51b3fSopenharmony_ciBM_DEFINE_bool(benchmark_enable_random_interleaving, false);
98a8c51b3fSopenharmony_ci
99a8c51b3fSopenharmony_ci// Report the result of each benchmark repetitions. When 'true' is specified
100a8c51b3fSopenharmony_ci// only the mean, standard deviation, and other statistics are reported for
101a8c51b3fSopenharmony_ci// repeated benchmarks. Affects all reporters.
102a8c51b3fSopenharmony_ciBM_DEFINE_bool(benchmark_report_aggregates_only, false);
103a8c51b3fSopenharmony_ci
104a8c51b3fSopenharmony_ci// Display the result of each benchmark repetitions. When 'true' is specified
105a8c51b3fSopenharmony_ci// only the mean, standard deviation, and other statistics are displayed for
106a8c51b3fSopenharmony_ci// repeated benchmarks. Unlike benchmark_report_aggregates_only, only affects
107a8c51b3fSopenharmony_ci// the display reporter, but  *NOT* file reporter, which will still contain
108a8c51b3fSopenharmony_ci// all the output.
109a8c51b3fSopenharmony_ciBM_DEFINE_bool(benchmark_display_aggregates_only, false);
110a8c51b3fSopenharmony_ci
111a8c51b3fSopenharmony_ci// The format to use for console output.
112a8c51b3fSopenharmony_ci// Valid values are 'console', 'json', or 'csv'.
113a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_format, "console");
114a8c51b3fSopenharmony_ci
115a8c51b3fSopenharmony_ci// The format to use for file output.
116a8c51b3fSopenharmony_ci// Valid values are 'console', 'json', or 'csv'.
117a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_out_format, "json");
118a8c51b3fSopenharmony_ci
119a8c51b3fSopenharmony_ci// The file to write additional output to.
120a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_out, "");
121a8c51b3fSopenharmony_ci
122a8c51b3fSopenharmony_ci// Whether to use colors in the output.  Valid values:
123a8c51b3fSopenharmony_ci// 'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use colors if
124a8c51b3fSopenharmony_ci// the output is being sent to a terminal and the TERM environment variable is
125a8c51b3fSopenharmony_ci// set to a terminal type that supports colors.
126a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_color, "auto");
127a8c51b3fSopenharmony_ci
128a8c51b3fSopenharmony_ci// Whether to use tabular format when printing user counters to the console.
129a8c51b3fSopenharmony_ci// Valid values: 'true'/'yes'/1, 'false'/'no'/0.  Defaults to false.
130a8c51b3fSopenharmony_ciBM_DEFINE_bool(benchmark_counters_tabular, false);
131a8c51b3fSopenharmony_ci
132a8c51b3fSopenharmony_ci// List of additional perf counters to collect, in libpfm format. For more
133a8c51b3fSopenharmony_ci// information about libpfm: https://man7.org/linux/man-pages/man3/libpfm.3.html
134a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_perf_counters, "");
135a8c51b3fSopenharmony_ci
136a8c51b3fSopenharmony_ci// Extra context to include in the output formatted as comma-separated key-value
137a8c51b3fSopenharmony_ci// pairs. Kept internal as it's only used for parsing from env/command line.
138a8c51b3fSopenharmony_ciBM_DEFINE_kvpairs(benchmark_context, {});
139a8c51b3fSopenharmony_ci
140a8c51b3fSopenharmony_ci// Set the default time unit to use for reports
141a8c51b3fSopenharmony_ci// Valid values are 'ns', 'us', 'ms' or 's'
142a8c51b3fSopenharmony_ciBM_DEFINE_string(benchmark_time_unit, "");
143a8c51b3fSopenharmony_ci
144a8c51b3fSopenharmony_ci// The level of verbose logging to output
145a8c51b3fSopenharmony_ciBM_DEFINE_int32(v, 0);
146a8c51b3fSopenharmony_ci
147a8c51b3fSopenharmony_cinamespace internal {
148a8c51b3fSopenharmony_ci
149a8c51b3fSopenharmony_cistd::map<std::string, std::string>* global_context = nullptr;
150a8c51b3fSopenharmony_ci
151a8c51b3fSopenharmony_ciBENCHMARK_EXPORT std::map<std::string, std::string>*& GetGlobalContext() {
152a8c51b3fSopenharmony_ci  return global_context;
153a8c51b3fSopenharmony_ci}
154a8c51b3fSopenharmony_ci
155a8c51b3fSopenharmony_ci// FIXME: wouldn't LTO mess this up?
156a8c51b3fSopenharmony_civoid UseCharPointer(char const volatile*) {}
157a8c51b3fSopenharmony_ci
158a8c51b3fSopenharmony_ci}  // namespace internal
159a8c51b3fSopenharmony_ci
160a8c51b3fSopenharmony_ciState::State(std::string name, IterationCount max_iters,
161a8c51b3fSopenharmony_ci             const std::vector<int64_t>& ranges, int thread_i, int n_threads,
162a8c51b3fSopenharmony_ci             internal::ThreadTimer* timer, internal::ThreadManager* manager,
163a8c51b3fSopenharmony_ci             internal::PerfCountersMeasurement* perf_counters_measurement)
164a8c51b3fSopenharmony_ci    : total_iterations_(0),
165a8c51b3fSopenharmony_ci      batch_leftover_(0),
166a8c51b3fSopenharmony_ci      max_iterations(max_iters),
167a8c51b3fSopenharmony_ci      started_(false),
168a8c51b3fSopenharmony_ci      finished_(false),
169a8c51b3fSopenharmony_ci      skipped_(internal::NotSkipped),
170a8c51b3fSopenharmony_ci      range_(ranges),
171a8c51b3fSopenharmony_ci      complexity_n_(0),
172a8c51b3fSopenharmony_ci      name_(std::move(name)),
173a8c51b3fSopenharmony_ci      thread_index_(thread_i),
174a8c51b3fSopenharmony_ci      threads_(n_threads),
175a8c51b3fSopenharmony_ci      timer_(timer),
176a8c51b3fSopenharmony_ci      manager_(manager),
177a8c51b3fSopenharmony_ci      perf_counters_measurement_(perf_counters_measurement) {
178a8c51b3fSopenharmony_ci  BM_CHECK(max_iterations != 0) << "At least one iteration must be run";
179a8c51b3fSopenharmony_ci  BM_CHECK_LT(thread_index_, threads_)
180a8c51b3fSopenharmony_ci      << "thread_index must be less than threads";
181a8c51b3fSopenharmony_ci
182a8c51b3fSopenharmony_ci  // Add counters with correct flag now.  If added with `counters[name]` in
183a8c51b3fSopenharmony_ci  // `PauseTiming`, a new `Counter` will be inserted the first time, which
184a8c51b3fSopenharmony_ci  // won't have the flag.  Inserting them now also reduces the allocations
185a8c51b3fSopenharmony_ci  // during the benchmark.
186a8c51b3fSopenharmony_ci  if (perf_counters_measurement_) {
187a8c51b3fSopenharmony_ci    for (const std::string& counter_name :
188a8c51b3fSopenharmony_ci         perf_counters_measurement_->names()) {
189a8c51b3fSopenharmony_ci      counters[counter_name] = Counter(0.0, Counter::kAvgIterations);
190a8c51b3fSopenharmony_ci    }
191a8c51b3fSopenharmony_ci  }
192a8c51b3fSopenharmony_ci
193a8c51b3fSopenharmony_ci  // Note: The use of offsetof below is technically undefined until C++17
194a8c51b3fSopenharmony_ci  // because State is not a standard layout type. However, all compilers
195a8c51b3fSopenharmony_ci  // currently provide well-defined behavior as an extension (which is
196a8c51b3fSopenharmony_ci  // demonstrated since constexpr evaluation must diagnose all undefined
197a8c51b3fSopenharmony_ci  // behavior). However, GCC and Clang also warn about this use of offsetof,
198a8c51b3fSopenharmony_ci  // which must be suppressed.
199a8c51b3fSopenharmony_ci#if defined(__INTEL_COMPILER)
200a8c51b3fSopenharmony_ci#pragma warning push
201a8c51b3fSopenharmony_ci#pragma warning(disable : 1875)
202a8c51b3fSopenharmony_ci#elif defined(__GNUC__)
203a8c51b3fSopenharmony_ci#pragma GCC diagnostic push
204a8c51b3fSopenharmony_ci#pragma GCC diagnostic ignored "-Winvalid-offsetof"
205a8c51b3fSopenharmony_ci#endif
206a8c51b3fSopenharmony_ci#if defined(__NVCC__)
207a8c51b3fSopenharmony_ci#pragma nv_diagnostic push
208a8c51b3fSopenharmony_ci#pragma nv_diag_suppress 1427
209a8c51b3fSopenharmony_ci#endif
210a8c51b3fSopenharmony_ci#if defined(__NVCOMPILER)
211a8c51b3fSopenharmony_ci#pragma diagnostic push
212a8c51b3fSopenharmony_ci#pragma diag_suppress offset_in_non_POD_nonstandard
213a8c51b3fSopenharmony_ci#endif
214a8c51b3fSopenharmony_ci  // Offset tests to ensure commonly accessed data is on the first cache line.
215a8c51b3fSopenharmony_ci  const int cache_line_size = 64;
216a8c51b3fSopenharmony_ci  static_assert(
217a8c51b3fSopenharmony_ci      offsetof(State, skipped_) <= (cache_line_size - sizeof(skipped_)), "");
218a8c51b3fSopenharmony_ci#if defined(__INTEL_COMPILER)
219a8c51b3fSopenharmony_ci#pragma warning pop
220a8c51b3fSopenharmony_ci#elif defined(__GNUC__)
221a8c51b3fSopenharmony_ci#pragma GCC diagnostic pop
222a8c51b3fSopenharmony_ci#endif
223a8c51b3fSopenharmony_ci#if defined(__NVCC__)
224a8c51b3fSopenharmony_ci#pragma nv_diagnostic pop
225a8c51b3fSopenharmony_ci#endif
226a8c51b3fSopenharmony_ci#if defined(__NVCOMPILER)
227a8c51b3fSopenharmony_ci#pragma diagnostic pop
228a8c51b3fSopenharmony_ci#endif
229a8c51b3fSopenharmony_ci}
230a8c51b3fSopenharmony_ci
231a8c51b3fSopenharmony_civoid State::PauseTiming() {
232a8c51b3fSopenharmony_ci  // Add in time accumulated so far
233a8c51b3fSopenharmony_ci  BM_CHECK(started_ && !finished_ && !skipped());
234a8c51b3fSopenharmony_ci  timer_->StopTimer();
235a8c51b3fSopenharmony_ci  if (perf_counters_measurement_) {
236a8c51b3fSopenharmony_ci    std::vector<std::pair<std::string, double>> measurements;
237a8c51b3fSopenharmony_ci    if (!perf_counters_measurement_->Stop(measurements)) {
238a8c51b3fSopenharmony_ci      BM_CHECK(false) << "Perf counters read the value failed.";
239a8c51b3fSopenharmony_ci    }
240a8c51b3fSopenharmony_ci    for (const auto& name_and_measurement : measurements) {
241a8c51b3fSopenharmony_ci      const std::string& name = name_and_measurement.first;
242a8c51b3fSopenharmony_ci      const double measurement = name_and_measurement.second;
243a8c51b3fSopenharmony_ci      // Counter was inserted with `kAvgIterations` flag by the constructor.
244a8c51b3fSopenharmony_ci      assert(counters.find(name) != counters.end());
245a8c51b3fSopenharmony_ci      counters[name].value += measurement;
246a8c51b3fSopenharmony_ci    }
247a8c51b3fSopenharmony_ci  }
248a8c51b3fSopenharmony_ci}
249a8c51b3fSopenharmony_ci
250a8c51b3fSopenharmony_civoid State::ResumeTiming() {
251a8c51b3fSopenharmony_ci  BM_CHECK(started_ && !finished_ && !skipped());
252a8c51b3fSopenharmony_ci  timer_->StartTimer();
253a8c51b3fSopenharmony_ci  if (perf_counters_measurement_) {
254a8c51b3fSopenharmony_ci    perf_counters_measurement_->Start();
255a8c51b3fSopenharmony_ci  }
256a8c51b3fSopenharmony_ci}
257a8c51b3fSopenharmony_ci
258a8c51b3fSopenharmony_civoid State::SkipWithMessage(const std::string& msg) {
259a8c51b3fSopenharmony_ci  skipped_ = internal::SkippedWithMessage;
260a8c51b3fSopenharmony_ci  {
261a8c51b3fSopenharmony_ci    MutexLock l(manager_->GetBenchmarkMutex());
262a8c51b3fSopenharmony_ci    if (internal::NotSkipped == manager_->results.skipped_) {
263a8c51b3fSopenharmony_ci      manager_->results.skip_message_ = msg;
264a8c51b3fSopenharmony_ci      manager_->results.skipped_ = skipped_;
265a8c51b3fSopenharmony_ci    }
266a8c51b3fSopenharmony_ci  }
267a8c51b3fSopenharmony_ci  total_iterations_ = 0;
268a8c51b3fSopenharmony_ci  if (timer_->running()) timer_->StopTimer();
269a8c51b3fSopenharmony_ci}
270a8c51b3fSopenharmony_ci
271a8c51b3fSopenharmony_civoid State::SkipWithError(const std::string& msg) {
272a8c51b3fSopenharmony_ci  skipped_ = internal::SkippedWithError;
273a8c51b3fSopenharmony_ci  {
274a8c51b3fSopenharmony_ci    MutexLock l(manager_->GetBenchmarkMutex());
275a8c51b3fSopenharmony_ci    if (internal::NotSkipped == manager_->results.skipped_) {
276a8c51b3fSopenharmony_ci      manager_->results.skip_message_ = msg;
277a8c51b3fSopenharmony_ci      manager_->results.skipped_ = skipped_;
278a8c51b3fSopenharmony_ci    }
279a8c51b3fSopenharmony_ci  }
280a8c51b3fSopenharmony_ci  total_iterations_ = 0;
281a8c51b3fSopenharmony_ci  if (timer_->running()) timer_->StopTimer();
282a8c51b3fSopenharmony_ci}
283a8c51b3fSopenharmony_ci
284a8c51b3fSopenharmony_civoid State::SetIterationTime(double seconds) {
285a8c51b3fSopenharmony_ci  timer_->SetIterationTime(seconds);
286a8c51b3fSopenharmony_ci}
287a8c51b3fSopenharmony_ci
288a8c51b3fSopenharmony_civoid State::SetLabel(const std::string& label) {
289a8c51b3fSopenharmony_ci  MutexLock l(manager_->GetBenchmarkMutex());
290a8c51b3fSopenharmony_ci  manager_->results.report_label_ = label;
291a8c51b3fSopenharmony_ci}
292a8c51b3fSopenharmony_ci
293a8c51b3fSopenharmony_civoid State::StartKeepRunning() {
294a8c51b3fSopenharmony_ci  BM_CHECK(!started_ && !finished_);
295a8c51b3fSopenharmony_ci  started_ = true;
296a8c51b3fSopenharmony_ci  total_iterations_ = skipped() ? 0 : max_iterations;
297a8c51b3fSopenharmony_ci  manager_->StartStopBarrier();
298a8c51b3fSopenharmony_ci  if (!skipped()) ResumeTiming();
299a8c51b3fSopenharmony_ci}
300a8c51b3fSopenharmony_ci
301a8c51b3fSopenharmony_civoid State::FinishKeepRunning() {
302a8c51b3fSopenharmony_ci  BM_CHECK(started_ && (!finished_ || skipped()));
303a8c51b3fSopenharmony_ci  if (!skipped()) {
304a8c51b3fSopenharmony_ci    PauseTiming();
305a8c51b3fSopenharmony_ci  }
306a8c51b3fSopenharmony_ci  // Total iterations has now wrapped around past 0. Fix this.
307a8c51b3fSopenharmony_ci  total_iterations_ = 0;
308a8c51b3fSopenharmony_ci  finished_ = true;
309a8c51b3fSopenharmony_ci  manager_->StartStopBarrier();
310a8c51b3fSopenharmony_ci}
311a8c51b3fSopenharmony_ci
312a8c51b3fSopenharmony_cinamespace internal {
313a8c51b3fSopenharmony_cinamespace {
314a8c51b3fSopenharmony_ci
315a8c51b3fSopenharmony_ci// Flushes streams after invoking reporter methods that write to them. This
316a8c51b3fSopenharmony_ci// ensures users get timely updates even when streams are not line-buffered.
317a8c51b3fSopenharmony_civoid FlushStreams(BenchmarkReporter* reporter) {
318a8c51b3fSopenharmony_ci  if (!reporter) return;
319a8c51b3fSopenharmony_ci  std::flush(reporter->GetOutputStream());
320a8c51b3fSopenharmony_ci  std::flush(reporter->GetErrorStream());
321a8c51b3fSopenharmony_ci}
322a8c51b3fSopenharmony_ci
323a8c51b3fSopenharmony_ci// Reports in both display and file reporters.
324a8c51b3fSopenharmony_civoid Report(BenchmarkReporter* display_reporter,
325a8c51b3fSopenharmony_ci            BenchmarkReporter* file_reporter, const RunResults& run_results) {
326a8c51b3fSopenharmony_ci  auto report_one = [](BenchmarkReporter* reporter, bool aggregates_only,
327a8c51b3fSopenharmony_ci                       const RunResults& results) {
328a8c51b3fSopenharmony_ci    assert(reporter);
329a8c51b3fSopenharmony_ci    // If there are no aggregates, do output non-aggregates.
330a8c51b3fSopenharmony_ci    aggregates_only &= !results.aggregates_only.empty();
331a8c51b3fSopenharmony_ci    if (!aggregates_only) reporter->ReportRuns(results.non_aggregates);
332a8c51b3fSopenharmony_ci    if (!results.aggregates_only.empty())
333a8c51b3fSopenharmony_ci      reporter->ReportRuns(results.aggregates_only);
334a8c51b3fSopenharmony_ci  };
335a8c51b3fSopenharmony_ci
336a8c51b3fSopenharmony_ci  report_one(display_reporter, run_results.display_report_aggregates_only,
337a8c51b3fSopenharmony_ci             run_results);
338a8c51b3fSopenharmony_ci  if (file_reporter)
339a8c51b3fSopenharmony_ci    report_one(file_reporter, run_results.file_report_aggregates_only,
340a8c51b3fSopenharmony_ci               run_results);
341a8c51b3fSopenharmony_ci
342a8c51b3fSopenharmony_ci  FlushStreams(display_reporter);
343a8c51b3fSopenharmony_ci  FlushStreams(file_reporter);
344a8c51b3fSopenharmony_ci}
345a8c51b3fSopenharmony_ci
346a8c51b3fSopenharmony_civoid RunBenchmarks(const std::vector<BenchmarkInstance>& benchmarks,
347a8c51b3fSopenharmony_ci                   BenchmarkReporter* display_reporter,
348a8c51b3fSopenharmony_ci                   BenchmarkReporter* file_reporter) {
349a8c51b3fSopenharmony_ci  // Note the file_reporter can be null.
350a8c51b3fSopenharmony_ci  BM_CHECK(display_reporter != nullptr);
351a8c51b3fSopenharmony_ci
352a8c51b3fSopenharmony_ci  // Determine the width of the name field using a minimum width of 10.
353a8c51b3fSopenharmony_ci  bool might_have_aggregates = FLAGS_benchmark_repetitions > 1;
354a8c51b3fSopenharmony_ci  size_t name_field_width = 10;
355a8c51b3fSopenharmony_ci  size_t stat_field_width = 0;
356a8c51b3fSopenharmony_ci  for (const BenchmarkInstance& benchmark : benchmarks) {
357a8c51b3fSopenharmony_ci    name_field_width =
358a8c51b3fSopenharmony_ci        std::max<size_t>(name_field_width, benchmark.name().str().size());
359a8c51b3fSopenharmony_ci    might_have_aggregates |= benchmark.repetitions() > 1;
360a8c51b3fSopenharmony_ci
361a8c51b3fSopenharmony_ci    for (const auto& Stat : benchmark.statistics())
362a8c51b3fSopenharmony_ci      stat_field_width = std::max<size_t>(stat_field_width, Stat.name_.size());
363a8c51b3fSopenharmony_ci  }
364a8c51b3fSopenharmony_ci  if (might_have_aggregates) name_field_width += 1 + stat_field_width;
365a8c51b3fSopenharmony_ci
366a8c51b3fSopenharmony_ci  // Print header here
367a8c51b3fSopenharmony_ci  BenchmarkReporter::Context context;
368a8c51b3fSopenharmony_ci  context.name_field_width = name_field_width;
369a8c51b3fSopenharmony_ci
370a8c51b3fSopenharmony_ci  // Keep track of running times of all instances of each benchmark family.
371a8c51b3fSopenharmony_ci  std::map<int /*family_index*/, BenchmarkReporter::PerFamilyRunReports>
372a8c51b3fSopenharmony_ci      per_family_reports;
373a8c51b3fSopenharmony_ci
374a8c51b3fSopenharmony_ci  if (display_reporter->ReportContext(context) &&
375a8c51b3fSopenharmony_ci      (!file_reporter || file_reporter->ReportContext(context))) {
376a8c51b3fSopenharmony_ci    FlushStreams(display_reporter);
377a8c51b3fSopenharmony_ci    FlushStreams(file_reporter);
378a8c51b3fSopenharmony_ci
379a8c51b3fSopenharmony_ci    size_t num_repetitions_total = 0;
380a8c51b3fSopenharmony_ci
381a8c51b3fSopenharmony_ci    // This perfcounters object needs to be created before the runners vector
382a8c51b3fSopenharmony_ci    // below so it outlasts their lifetime.
383a8c51b3fSopenharmony_ci    PerfCountersMeasurement perfcounters(
384a8c51b3fSopenharmony_ci        StrSplit(FLAGS_benchmark_perf_counters, ','));
385a8c51b3fSopenharmony_ci
386a8c51b3fSopenharmony_ci    // Vector of benchmarks to run
387a8c51b3fSopenharmony_ci    std::vector<internal::BenchmarkRunner> runners;
388a8c51b3fSopenharmony_ci    runners.reserve(benchmarks.size());
389a8c51b3fSopenharmony_ci
390a8c51b3fSopenharmony_ci    // Count the number of benchmarks with threads to warn the user in case
391a8c51b3fSopenharmony_ci    // performance counters are used.
392a8c51b3fSopenharmony_ci    int benchmarks_with_threads = 0;
393a8c51b3fSopenharmony_ci
394a8c51b3fSopenharmony_ci    // Loop through all benchmarks
395a8c51b3fSopenharmony_ci    for (const BenchmarkInstance& benchmark : benchmarks) {
396a8c51b3fSopenharmony_ci      BenchmarkReporter::PerFamilyRunReports* reports_for_family = nullptr;
397a8c51b3fSopenharmony_ci      if (benchmark.complexity() != oNone)
398a8c51b3fSopenharmony_ci        reports_for_family = &per_family_reports[benchmark.family_index()];
399a8c51b3fSopenharmony_ci      benchmarks_with_threads += (benchmark.threads() > 1);
400a8c51b3fSopenharmony_ci      runners.emplace_back(benchmark, &perfcounters, reports_for_family);
401a8c51b3fSopenharmony_ci      int num_repeats_of_this_instance = runners.back().GetNumRepeats();
402a8c51b3fSopenharmony_ci      num_repetitions_total += num_repeats_of_this_instance;
403a8c51b3fSopenharmony_ci      if (reports_for_family)
404a8c51b3fSopenharmony_ci        reports_for_family->num_runs_total += num_repeats_of_this_instance;
405a8c51b3fSopenharmony_ci    }
406a8c51b3fSopenharmony_ci    assert(runners.size() == benchmarks.size() && "Unexpected runner count.");
407a8c51b3fSopenharmony_ci
408a8c51b3fSopenharmony_ci    // The use of performance counters with threads would be unintuitive for
409a8c51b3fSopenharmony_ci    // the average user so we need to warn them about this case
410a8c51b3fSopenharmony_ci    if ((benchmarks_with_threads > 0) && (perfcounters.num_counters() > 0)) {
411a8c51b3fSopenharmony_ci      GetErrorLogInstance()
412a8c51b3fSopenharmony_ci          << "***WARNING*** There are " << benchmarks_with_threads
413a8c51b3fSopenharmony_ci          << " benchmarks with threads and " << perfcounters.num_counters()
414a8c51b3fSopenharmony_ci          << " performance counters were requested. Beware counters will "
415a8c51b3fSopenharmony_ci             "reflect the combined usage across all "
416a8c51b3fSopenharmony_ci             "threads.\n";
417a8c51b3fSopenharmony_ci    }
418a8c51b3fSopenharmony_ci
419a8c51b3fSopenharmony_ci    std::vector<size_t> repetition_indices;
420a8c51b3fSopenharmony_ci    repetition_indices.reserve(num_repetitions_total);
421a8c51b3fSopenharmony_ci    for (size_t runner_index = 0, num_runners = runners.size();
422a8c51b3fSopenharmony_ci         runner_index != num_runners; ++runner_index) {
423a8c51b3fSopenharmony_ci      const internal::BenchmarkRunner& runner = runners[runner_index];
424a8c51b3fSopenharmony_ci      std::fill_n(std::back_inserter(repetition_indices),
425a8c51b3fSopenharmony_ci                  runner.GetNumRepeats(), runner_index);
426a8c51b3fSopenharmony_ci    }
427a8c51b3fSopenharmony_ci    assert(repetition_indices.size() == num_repetitions_total &&
428a8c51b3fSopenharmony_ci           "Unexpected number of repetition indexes.");
429a8c51b3fSopenharmony_ci
430a8c51b3fSopenharmony_ci    if (FLAGS_benchmark_enable_random_interleaving) {
431a8c51b3fSopenharmony_ci      std::random_device rd;
432a8c51b3fSopenharmony_ci      std::mt19937 g(rd());
433a8c51b3fSopenharmony_ci      std::shuffle(repetition_indices.begin(), repetition_indices.end(), g);
434a8c51b3fSopenharmony_ci    }
435a8c51b3fSopenharmony_ci
436a8c51b3fSopenharmony_ci    for (size_t repetition_index : repetition_indices) {
437a8c51b3fSopenharmony_ci      internal::BenchmarkRunner& runner = runners[repetition_index];
438a8c51b3fSopenharmony_ci      runner.DoOneRepetition();
439a8c51b3fSopenharmony_ci      if (runner.HasRepeatsRemaining()) continue;
440a8c51b3fSopenharmony_ci      // FIXME: report each repetition separately, not all of them in bulk.
441a8c51b3fSopenharmony_ci
442a8c51b3fSopenharmony_ci      display_reporter->ReportRunsConfig(
443a8c51b3fSopenharmony_ci          runner.GetMinTime(), runner.HasExplicitIters(), runner.GetIters());
444a8c51b3fSopenharmony_ci      if (file_reporter)
445a8c51b3fSopenharmony_ci        file_reporter->ReportRunsConfig(
446a8c51b3fSopenharmony_ci            runner.GetMinTime(), runner.HasExplicitIters(), runner.GetIters());
447a8c51b3fSopenharmony_ci
448a8c51b3fSopenharmony_ci      RunResults run_results = runner.GetResults();
449a8c51b3fSopenharmony_ci
450a8c51b3fSopenharmony_ci      // Maybe calculate complexity report
451a8c51b3fSopenharmony_ci      if (const auto* reports_for_family = runner.GetReportsForFamily()) {
452a8c51b3fSopenharmony_ci        if (reports_for_family->num_runs_done ==
453a8c51b3fSopenharmony_ci            reports_for_family->num_runs_total) {
454a8c51b3fSopenharmony_ci          auto additional_run_stats = ComputeBigO(reports_for_family->Runs);
455a8c51b3fSopenharmony_ci          run_results.aggregates_only.insert(run_results.aggregates_only.end(),
456a8c51b3fSopenharmony_ci                                             additional_run_stats.begin(),
457a8c51b3fSopenharmony_ci                                             additional_run_stats.end());
458a8c51b3fSopenharmony_ci          per_family_reports.erase(
459a8c51b3fSopenharmony_ci              static_cast<int>(reports_for_family->Runs.front().family_index));
460a8c51b3fSopenharmony_ci        }
461a8c51b3fSopenharmony_ci      }
462a8c51b3fSopenharmony_ci
463a8c51b3fSopenharmony_ci      Report(display_reporter, file_reporter, run_results);
464a8c51b3fSopenharmony_ci    }
465a8c51b3fSopenharmony_ci  }
466a8c51b3fSopenharmony_ci  display_reporter->Finalize();
467a8c51b3fSopenharmony_ci  if (file_reporter) file_reporter->Finalize();
468a8c51b3fSopenharmony_ci  FlushStreams(display_reporter);
469a8c51b3fSopenharmony_ci  FlushStreams(file_reporter);
470a8c51b3fSopenharmony_ci}
471a8c51b3fSopenharmony_ci
472a8c51b3fSopenharmony_ci// Disable deprecated warnings temporarily because we need to reference
473a8c51b3fSopenharmony_ci// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations
474a8c51b3fSopenharmony_ciBENCHMARK_DISABLE_DEPRECATED_WARNING
475a8c51b3fSopenharmony_ci
476a8c51b3fSopenharmony_cistd::unique_ptr<BenchmarkReporter> CreateReporter(
477a8c51b3fSopenharmony_ci    std::string const& name, ConsoleReporter::OutputOptions output_opts) {
478a8c51b3fSopenharmony_ci  typedef std::unique_ptr<BenchmarkReporter> PtrType;
479a8c51b3fSopenharmony_ci  if (name == "console") {
480a8c51b3fSopenharmony_ci    return PtrType(new ConsoleReporter(output_opts));
481a8c51b3fSopenharmony_ci  }
482a8c51b3fSopenharmony_ci  if (name == "json") {
483a8c51b3fSopenharmony_ci    return PtrType(new JSONReporter());
484a8c51b3fSopenharmony_ci  }
485a8c51b3fSopenharmony_ci  if (name == "csv") {
486a8c51b3fSopenharmony_ci    return PtrType(new CSVReporter());
487a8c51b3fSopenharmony_ci  }
488a8c51b3fSopenharmony_ci  std::cerr << "Unexpected format: '" << name << "'\n";
489a8c51b3fSopenharmony_ci  std::exit(1);
490a8c51b3fSopenharmony_ci}
491a8c51b3fSopenharmony_ci
492a8c51b3fSopenharmony_ciBENCHMARK_RESTORE_DEPRECATED_WARNING
493a8c51b3fSopenharmony_ci
494a8c51b3fSopenharmony_ci}  // end namespace
495a8c51b3fSopenharmony_ci
496a8c51b3fSopenharmony_cibool IsZero(double n) {
497a8c51b3fSopenharmony_ci  return std::abs(n) < std::numeric_limits<double>::epsilon();
498a8c51b3fSopenharmony_ci}
499a8c51b3fSopenharmony_ci
500a8c51b3fSopenharmony_ciConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
501a8c51b3fSopenharmony_ci  int output_opts = ConsoleReporter::OO_Defaults;
502a8c51b3fSopenharmony_ci  auto is_benchmark_color = [force_no_color]() -> bool {
503a8c51b3fSopenharmony_ci    if (force_no_color) {
504a8c51b3fSopenharmony_ci      return false;
505a8c51b3fSopenharmony_ci    }
506a8c51b3fSopenharmony_ci    if (FLAGS_benchmark_color == "auto") {
507a8c51b3fSopenharmony_ci      return IsColorTerminal();
508a8c51b3fSopenharmony_ci    }
509a8c51b3fSopenharmony_ci    return IsTruthyFlagValue(FLAGS_benchmark_color);
510a8c51b3fSopenharmony_ci  };
511a8c51b3fSopenharmony_ci  if (is_benchmark_color()) {
512a8c51b3fSopenharmony_ci    output_opts |= ConsoleReporter::OO_Color;
513a8c51b3fSopenharmony_ci  } else {
514a8c51b3fSopenharmony_ci    output_opts &= ~ConsoleReporter::OO_Color;
515a8c51b3fSopenharmony_ci  }
516a8c51b3fSopenharmony_ci  if (FLAGS_benchmark_counters_tabular) {
517a8c51b3fSopenharmony_ci    output_opts |= ConsoleReporter::OO_Tabular;
518a8c51b3fSopenharmony_ci  } else {
519a8c51b3fSopenharmony_ci    output_opts &= ~ConsoleReporter::OO_Tabular;
520a8c51b3fSopenharmony_ci  }
521a8c51b3fSopenharmony_ci  return static_cast<ConsoleReporter::OutputOptions>(output_opts);
522a8c51b3fSopenharmony_ci}
523a8c51b3fSopenharmony_ci
524a8c51b3fSopenharmony_ci}  // end namespace internal
525a8c51b3fSopenharmony_ci
526a8c51b3fSopenharmony_ciBenchmarkReporter* CreateDefaultDisplayReporter() {
527a8c51b3fSopenharmony_ci  static auto default_display_reporter =
528a8c51b3fSopenharmony_ci      internal::CreateReporter(FLAGS_benchmark_format,
529a8c51b3fSopenharmony_ci                               internal::GetOutputOptions())
530a8c51b3fSopenharmony_ci          .release();
531a8c51b3fSopenharmony_ci  return default_display_reporter;
532a8c51b3fSopenharmony_ci}
533a8c51b3fSopenharmony_ci
534a8c51b3fSopenharmony_cisize_t RunSpecifiedBenchmarks() {
535a8c51b3fSopenharmony_ci  return RunSpecifiedBenchmarks(nullptr, nullptr, FLAGS_benchmark_filter);
536a8c51b3fSopenharmony_ci}
537a8c51b3fSopenharmony_ci
538a8c51b3fSopenharmony_cisize_t RunSpecifiedBenchmarks(std::string spec) {
539a8c51b3fSopenharmony_ci  return RunSpecifiedBenchmarks(nullptr, nullptr, std::move(spec));
540a8c51b3fSopenharmony_ci}
541a8c51b3fSopenharmony_ci
542a8c51b3fSopenharmony_cisize_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter) {
543a8c51b3fSopenharmony_ci  return RunSpecifiedBenchmarks(display_reporter, nullptr,
544a8c51b3fSopenharmony_ci                                FLAGS_benchmark_filter);
545a8c51b3fSopenharmony_ci}
546a8c51b3fSopenharmony_ci
547a8c51b3fSopenharmony_cisize_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
548a8c51b3fSopenharmony_ci                              std::string spec) {
549a8c51b3fSopenharmony_ci  return RunSpecifiedBenchmarks(display_reporter, nullptr, std::move(spec));
550a8c51b3fSopenharmony_ci}
551a8c51b3fSopenharmony_ci
552a8c51b3fSopenharmony_cisize_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
553a8c51b3fSopenharmony_ci                              BenchmarkReporter* file_reporter) {
554a8c51b3fSopenharmony_ci  return RunSpecifiedBenchmarks(display_reporter, file_reporter,
555a8c51b3fSopenharmony_ci                                FLAGS_benchmark_filter);
556a8c51b3fSopenharmony_ci}
557a8c51b3fSopenharmony_ci
558a8c51b3fSopenharmony_cisize_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
559a8c51b3fSopenharmony_ci                              BenchmarkReporter* file_reporter,
560a8c51b3fSopenharmony_ci                              std::string spec) {
561a8c51b3fSopenharmony_ci  if (spec.empty() || spec == "all")
562a8c51b3fSopenharmony_ci    spec = ".";  // Regexp that matches all benchmarks
563a8c51b3fSopenharmony_ci
564a8c51b3fSopenharmony_ci  // Setup the reporters
565a8c51b3fSopenharmony_ci  std::ofstream output_file;
566a8c51b3fSopenharmony_ci  std::unique_ptr<BenchmarkReporter> default_display_reporter;
567a8c51b3fSopenharmony_ci  std::unique_ptr<BenchmarkReporter> default_file_reporter;
568a8c51b3fSopenharmony_ci  if (!display_reporter) {
569a8c51b3fSopenharmony_ci    default_display_reporter.reset(CreateDefaultDisplayReporter());
570a8c51b3fSopenharmony_ci    display_reporter = default_display_reporter.get();
571a8c51b3fSopenharmony_ci  }
572a8c51b3fSopenharmony_ci  auto& Out = display_reporter->GetOutputStream();
573a8c51b3fSopenharmony_ci  auto& Err = display_reporter->GetErrorStream();
574a8c51b3fSopenharmony_ci
575a8c51b3fSopenharmony_ci  std::string const& fname = FLAGS_benchmark_out;
576a8c51b3fSopenharmony_ci  if (fname.empty() && file_reporter) {
577a8c51b3fSopenharmony_ci    Err << "A custom file reporter was provided but "
578a8c51b3fSopenharmony_ci           "--benchmark_out=<file> was not specified."
579a8c51b3fSopenharmony_ci        << std::endl;
580a8c51b3fSopenharmony_ci    std::exit(1);
581a8c51b3fSopenharmony_ci  }
582a8c51b3fSopenharmony_ci  if (!fname.empty()) {
583a8c51b3fSopenharmony_ci    output_file.open(fname);
584a8c51b3fSopenharmony_ci    if (!output_file.is_open()) {
585a8c51b3fSopenharmony_ci      Err << "invalid file name: '" << fname << "'" << std::endl;
586a8c51b3fSopenharmony_ci      std::exit(1);
587a8c51b3fSopenharmony_ci    }
588a8c51b3fSopenharmony_ci    if (!file_reporter) {
589a8c51b3fSopenharmony_ci      default_file_reporter = internal::CreateReporter(
590a8c51b3fSopenharmony_ci          FLAGS_benchmark_out_format, FLAGS_benchmark_counters_tabular
591a8c51b3fSopenharmony_ci                                          ? ConsoleReporter::OO_Tabular
592a8c51b3fSopenharmony_ci                                          : ConsoleReporter::OO_None);
593a8c51b3fSopenharmony_ci      file_reporter = default_file_reporter.get();
594a8c51b3fSopenharmony_ci    }
595a8c51b3fSopenharmony_ci    file_reporter->SetOutputStream(&output_file);
596a8c51b3fSopenharmony_ci    file_reporter->SetErrorStream(&output_file);
597a8c51b3fSopenharmony_ci  }
598a8c51b3fSopenharmony_ci
599a8c51b3fSopenharmony_ci  std::vector<internal::BenchmarkInstance> benchmarks;
600a8c51b3fSopenharmony_ci  if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) return 0;
601a8c51b3fSopenharmony_ci
602a8c51b3fSopenharmony_ci  if (benchmarks.empty()) {
603a8c51b3fSopenharmony_ci    Err << "Failed to match any benchmarks against regex: " << spec << "\n";
604a8c51b3fSopenharmony_ci    return 0;
605a8c51b3fSopenharmony_ci  }
606a8c51b3fSopenharmony_ci
607a8c51b3fSopenharmony_ci  if (FLAGS_benchmark_list_tests) {
608a8c51b3fSopenharmony_ci    for (auto const& benchmark : benchmarks)
609a8c51b3fSopenharmony_ci      Out << benchmark.name().str() << "\n";
610a8c51b3fSopenharmony_ci  } else {
611a8c51b3fSopenharmony_ci    internal::RunBenchmarks(benchmarks, display_reporter, file_reporter);
612a8c51b3fSopenharmony_ci  }
613a8c51b3fSopenharmony_ci
614a8c51b3fSopenharmony_ci  return benchmarks.size();
615a8c51b3fSopenharmony_ci}
616a8c51b3fSopenharmony_ci
617a8c51b3fSopenharmony_cinamespace {
618a8c51b3fSopenharmony_ci// stores the time unit benchmarks use by default
619a8c51b3fSopenharmony_ciTimeUnit default_time_unit = kNanosecond;
620a8c51b3fSopenharmony_ci}  // namespace
621a8c51b3fSopenharmony_ci
622a8c51b3fSopenharmony_ciTimeUnit GetDefaultTimeUnit() { return default_time_unit; }
623a8c51b3fSopenharmony_ci
624a8c51b3fSopenharmony_civoid SetDefaultTimeUnit(TimeUnit unit) { default_time_unit = unit; }
625a8c51b3fSopenharmony_ci
626a8c51b3fSopenharmony_cistd::string GetBenchmarkFilter() { return FLAGS_benchmark_filter; }
627a8c51b3fSopenharmony_ci
628a8c51b3fSopenharmony_civoid SetBenchmarkFilter(std::string value) {
629a8c51b3fSopenharmony_ci  FLAGS_benchmark_filter = std::move(value);
630a8c51b3fSopenharmony_ci}
631a8c51b3fSopenharmony_ci
632a8c51b3fSopenharmony_ciint32_t GetBenchmarkVerbosity() { return FLAGS_v; }
633a8c51b3fSopenharmony_ci
634a8c51b3fSopenharmony_civoid RegisterMemoryManager(MemoryManager* manager) {
635a8c51b3fSopenharmony_ci  internal::memory_manager = manager;
636a8c51b3fSopenharmony_ci}
637a8c51b3fSopenharmony_ci
638a8c51b3fSopenharmony_civoid AddCustomContext(const std::string& key, const std::string& value) {
639a8c51b3fSopenharmony_ci  if (internal::global_context == nullptr) {
640a8c51b3fSopenharmony_ci    internal::global_context = new std::map<std::string, std::string>();
641a8c51b3fSopenharmony_ci  }
642a8c51b3fSopenharmony_ci  if (!internal::global_context->emplace(key, value).second) {
643a8c51b3fSopenharmony_ci    std::cerr << "Failed to add custom context \"" << key << "\" as it already "
644a8c51b3fSopenharmony_ci              << "exists with value \"" << value << "\"\n";
645a8c51b3fSopenharmony_ci  }
646a8c51b3fSopenharmony_ci}
647a8c51b3fSopenharmony_ci
648a8c51b3fSopenharmony_cinamespace internal {
649a8c51b3fSopenharmony_ci
650a8c51b3fSopenharmony_civoid (*HelperPrintf)();
651a8c51b3fSopenharmony_ci
652a8c51b3fSopenharmony_civoid PrintUsageAndExit() {
653a8c51b3fSopenharmony_ci  HelperPrintf();
654a8c51b3fSopenharmony_ci  exit(0);
655a8c51b3fSopenharmony_ci}
656a8c51b3fSopenharmony_ci
657a8c51b3fSopenharmony_civoid SetDefaultTimeUnitFromFlag(const std::string& time_unit_flag) {
658a8c51b3fSopenharmony_ci  if (time_unit_flag == "s") {
659a8c51b3fSopenharmony_ci    return SetDefaultTimeUnit(kSecond);
660a8c51b3fSopenharmony_ci  }
661a8c51b3fSopenharmony_ci  if (time_unit_flag == "ms") {
662a8c51b3fSopenharmony_ci    return SetDefaultTimeUnit(kMillisecond);
663a8c51b3fSopenharmony_ci  }
664a8c51b3fSopenharmony_ci  if (time_unit_flag == "us") {
665a8c51b3fSopenharmony_ci    return SetDefaultTimeUnit(kMicrosecond);
666a8c51b3fSopenharmony_ci  }
667a8c51b3fSopenharmony_ci  if (time_unit_flag == "ns") {
668a8c51b3fSopenharmony_ci    return SetDefaultTimeUnit(kNanosecond);
669a8c51b3fSopenharmony_ci  }
670a8c51b3fSopenharmony_ci  if (!time_unit_flag.empty()) {
671a8c51b3fSopenharmony_ci    PrintUsageAndExit();
672a8c51b3fSopenharmony_ci  }
673a8c51b3fSopenharmony_ci}
674a8c51b3fSopenharmony_ci
675a8c51b3fSopenharmony_civoid ParseCommandLineFlags(int* argc, char** argv) {
676a8c51b3fSopenharmony_ci  using namespace benchmark;
677a8c51b3fSopenharmony_ci  BenchmarkReporter::Context::executable_name =
678a8c51b3fSopenharmony_ci      (argc && *argc > 0) ? argv[0] : "unknown";
679a8c51b3fSopenharmony_ci  for (int i = 1; argc && i < *argc; ++i) {
680a8c51b3fSopenharmony_ci    if (ParseBoolFlag(argv[i], "benchmark_list_tests",
681a8c51b3fSopenharmony_ci                      &FLAGS_benchmark_list_tests) ||
682a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) ||
683a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_min_time",
684a8c51b3fSopenharmony_ci                        &FLAGS_benchmark_min_time) ||
685a8c51b3fSopenharmony_ci        ParseDoubleFlag(argv[i], "benchmark_min_warmup_time",
686a8c51b3fSopenharmony_ci                        &FLAGS_benchmark_min_warmup_time) ||
687a8c51b3fSopenharmony_ci        ParseInt32Flag(argv[i], "benchmark_repetitions",
688a8c51b3fSopenharmony_ci                       &FLAGS_benchmark_repetitions) ||
689a8c51b3fSopenharmony_ci        ParseBoolFlag(argv[i], "benchmark_enable_random_interleaving",
690a8c51b3fSopenharmony_ci                      &FLAGS_benchmark_enable_random_interleaving) ||
691a8c51b3fSopenharmony_ci        ParseBoolFlag(argv[i], "benchmark_report_aggregates_only",
692a8c51b3fSopenharmony_ci                      &FLAGS_benchmark_report_aggregates_only) ||
693a8c51b3fSopenharmony_ci        ParseBoolFlag(argv[i], "benchmark_display_aggregates_only",
694a8c51b3fSopenharmony_ci                      &FLAGS_benchmark_display_aggregates_only) ||
695a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_format", &FLAGS_benchmark_format) ||
696a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_out", &FLAGS_benchmark_out) ||
697a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_out_format",
698a8c51b3fSopenharmony_ci                        &FLAGS_benchmark_out_format) ||
699a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_color", &FLAGS_benchmark_color) ||
700a8c51b3fSopenharmony_ci        ParseBoolFlag(argv[i], "benchmark_counters_tabular",
701a8c51b3fSopenharmony_ci                      &FLAGS_benchmark_counters_tabular) ||
702a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_perf_counters",
703a8c51b3fSopenharmony_ci                        &FLAGS_benchmark_perf_counters) ||
704a8c51b3fSopenharmony_ci        ParseKeyValueFlag(argv[i], "benchmark_context",
705a8c51b3fSopenharmony_ci                          &FLAGS_benchmark_context) ||
706a8c51b3fSopenharmony_ci        ParseStringFlag(argv[i], "benchmark_time_unit",
707a8c51b3fSopenharmony_ci                        &FLAGS_benchmark_time_unit) ||
708a8c51b3fSopenharmony_ci        ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
709a8c51b3fSopenharmony_ci      for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1];
710a8c51b3fSopenharmony_ci
711a8c51b3fSopenharmony_ci      --(*argc);
712a8c51b3fSopenharmony_ci      --i;
713a8c51b3fSopenharmony_ci    } else if (IsFlag(argv[i], "help")) {
714a8c51b3fSopenharmony_ci      PrintUsageAndExit();
715a8c51b3fSopenharmony_ci    }
716a8c51b3fSopenharmony_ci  }
717a8c51b3fSopenharmony_ci  for (auto const* flag :
718a8c51b3fSopenharmony_ci       {&FLAGS_benchmark_format, &FLAGS_benchmark_out_format}) {
719a8c51b3fSopenharmony_ci    if (*flag != "console" && *flag != "json" && *flag != "csv") {
720a8c51b3fSopenharmony_ci      PrintUsageAndExit();
721a8c51b3fSopenharmony_ci    }
722a8c51b3fSopenharmony_ci  }
723a8c51b3fSopenharmony_ci  SetDefaultTimeUnitFromFlag(FLAGS_benchmark_time_unit);
724a8c51b3fSopenharmony_ci  if (FLAGS_benchmark_color.empty()) {
725a8c51b3fSopenharmony_ci    PrintUsageAndExit();
726a8c51b3fSopenharmony_ci  }
727a8c51b3fSopenharmony_ci  for (const auto& kv : FLAGS_benchmark_context) {
728a8c51b3fSopenharmony_ci    AddCustomContext(kv.first, kv.second);
729a8c51b3fSopenharmony_ci  }
730a8c51b3fSopenharmony_ci}
731a8c51b3fSopenharmony_ci
732a8c51b3fSopenharmony_ciint InitializeStreams() {
733a8c51b3fSopenharmony_ci  static std::ios_base::Init init;
734a8c51b3fSopenharmony_ci  return 0;
735a8c51b3fSopenharmony_ci}
736a8c51b3fSopenharmony_ci
737a8c51b3fSopenharmony_ci}  // end namespace internal
738a8c51b3fSopenharmony_ci
739a8c51b3fSopenharmony_civoid PrintDefaultHelp() {
740a8c51b3fSopenharmony_ci  fprintf(stdout,
741a8c51b3fSopenharmony_ci          "benchmark"
742a8c51b3fSopenharmony_ci          " [--benchmark_list_tests={true|false}]\n"
743a8c51b3fSopenharmony_ci          "          [--benchmark_filter=<regex>]\n"
744a8c51b3fSopenharmony_ci          "          [--benchmark_min_time=`<integer>x` OR `<float>s` ]\n"
745a8c51b3fSopenharmony_ci          "          [--benchmark_min_warmup_time=<min_warmup_time>]\n"
746a8c51b3fSopenharmony_ci          "          [--benchmark_repetitions=<num_repetitions>]\n"
747a8c51b3fSopenharmony_ci          "          [--benchmark_enable_random_interleaving={true|false}]\n"
748a8c51b3fSopenharmony_ci          "          [--benchmark_report_aggregates_only={true|false}]\n"
749a8c51b3fSopenharmony_ci          "          [--benchmark_display_aggregates_only={true|false}]\n"
750a8c51b3fSopenharmony_ci          "          [--benchmark_format=<console|json|csv>]\n"
751a8c51b3fSopenharmony_ci          "          [--benchmark_out=<filename>]\n"
752a8c51b3fSopenharmony_ci          "          [--benchmark_out_format=<json|console|csv>]\n"
753a8c51b3fSopenharmony_ci          "          [--benchmark_color={auto|true|false}]\n"
754a8c51b3fSopenharmony_ci          "          [--benchmark_counters_tabular={true|false}]\n"
755a8c51b3fSopenharmony_ci#if defined HAVE_LIBPFM
756a8c51b3fSopenharmony_ci          "          [--benchmark_perf_counters=<counter>,...]\n"
757a8c51b3fSopenharmony_ci#endif
758a8c51b3fSopenharmony_ci          "          [--benchmark_context=<key>=<value>,...]\n"
759a8c51b3fSopenharmony_ci          "          [--benchmark_time_unit={ns|us|ms|s}]\n"
760a8c51b3fSopenharmony_ci          "          [--v=<verbosity>]\n");
761a8c51b3fSopenharmony_ci}
762a8c51b3fSopenharmony_ci
763a8c51b3fSopenharmony_civoid Initialize(int* argc, char** argv, void (*HelperPrintf)()) {
764a8c51b3fSopenharmony_ci  internal::HelperPrintf = HelperPrintf;
765a8c51b3fSopenharmony_ci  internal::ParseCommandLineFlags(argc, argv);
766a8c51b3fSopenharmony_ci  internal::LogLevel() = FLAGS_v;
767a8c51b3fSopenharmony_ci}
768a8c51b3fSopenharmony_ci
769a8c51b3fSopenharmony_civoid Shutdown() { delete internal::global_context; }
770a8c51b3fSopenharmony_ci
771a8c51b3fSopenharmony_cibool ReportUnrecognizedArguments(int argc, char** argv) {
772a8c51b3fSopenharmony_ci  for (int i = 1; i < argc; ++i) {
773a8c51b3fSopenharmony_ci    fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0],
774a8c51b3fSopenharmony_ci            argv[i]);
775a8c51b3fSopenharmony_ci  }
776a8c51b3fSopenharmony_ci  return argc > 1;
777a8c51b3fSopenharmony_ci}
778a8c51b3fSopenharmony_ci
779a8c51b3fSopenharmony_ci}  // end namespace benchmark
780