1*58b9f456SAndroid Build Coastguard Worker // Copyright 2015 Google Inc. All rights reserved.
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*58b9f456SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*58b9f456SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*58b9f456SAndroid Build Coastguard Worker //
7*58b9f456SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*58b9f456SAndroid Build Coastguard Worker //
9*58b9f456SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*58b9f456SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*58b9f456SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*58b9f456SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*58b9f456SAndroid Build Coastguard Worker // limitations under the License.
14*58b9f456SAndroid Build Coastguard Worker
15*58b9f456SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
16*58b9f456SAndroid Build Coastguard Worker #include "benchmark_api_internal.h"
17*58b9f456SAndroid Build Coastguard Worker #include "benchmark_runner.h"
18*58b9f456SAndroid Build Coastguard Worker #include "internal_macros.h"
19*58b9f456SAndroid Build Coastguard Worker
20*58b9f456SAndroid Build Coastguard Worker #ifndef BENCHMARK_OS_WINDOWS
21*58b9f456SAndroid Build Coastguard Worker #ifndef BENCHMARK_OS_FUCHSIA
22*58b9f456SAndroid Build Coastguard Worker #include <sys/resource.h>
23*58b9f456SAndroid Build Coastguard Worker #endif
24*58b9f456SAndroid Build Coastguard Worker #include <sys/time.h>
25*58b9f456SAndroid Build Coastguard Worker #include <unistd.h>
26*58b9f456SAndroid Build Coastguard Worker #endif
27*58b9f456SAndroid Build Coastguard Worker
28*58b9f456SAndroid Build Coastguard Worker #include <algorithm>
29*58b9f456SAndroid Build Coastguard Worker #include <atomic>
30*58b9f456SAndroid Build Coastguard Worker #include <condition_variable>
31*58b9f456SAndroid Build Coastguard Worker #include <cstdio>
32*58b9f456SAndroid Build Coastguard Worker #include <cstdlib>
33*58b9f456SAndroid Build Coastguard Worker #include <fstream>
34*58b9f456SAndroid Build Coastguard Worker #include <iostream>
35*58b9f456SAndroid Build Coastguard Worker #include <memory>
36*58b9f456SAndroid Build Coastguard Worker #include <string>
37*58b9f456SAndroid Build Coastguard Worker #include <thread>
38*58b9f456SAndroid Build Coastguard Worker #include <utility>
39*58b9f456SAndroid Build Coastguard Worker
40*58b9f456SAndroid Build Coastguard Worker #include "check.h"
41*58b9f456SAndroid Build Coastguard Worker #include "colorprint.h"
42*58b9f456SAndroid Build Coastguard Worker #include "commandlineflags.h"
43*58b9f456SAndroid Build Coastguard Worker #include "complexity.h"
44*58b9f456SAndroid Build Coastguard Worker #include "counter.h"
45*58b9f456SAndroid Build Coastguard Worker #include "internal_macros.h"
46*58b9f456SAndroid Build Coastguard Worker #include "log.h"
47*58b9f456SAndroid Build Coastguard Worker #include "mutex.h"
48*58b9f456SAndroid Build Coastguard Worker #include "re.h"
49*58b9f456SAndroid Build Coastguard Worker #include "statistics.h"
50*58b9f456SAndroid Build Coastguard Worker #include "string_util.h"
51*58b9f456SAndroid Build Coastguard Worker #include "thread_manager.h"
52*58b9f456SAndroid Build Coastguard Worker #include "thread_timer.h"
53*58b9f456SAndroid Build Coastguard Worker
54*58b9f456SAndroid Build Coastguard Worker DEFINE_bool(benchmark_list_tests, false,
55*58b9f456SAndroid Build Coastguard Worker "Print a list of benchmarks. This option overrides all other "
56*58b9f456SAndroid Build Coastguard Worker "options.");
57*58b9f456SAndroid Build Coastguard Worker
58*58b9f456SAndroid Build Coastguard Worker DEFINE_string(benchmark_filter, ".",
59*58b9f456SAndroid Build Coastguard Worker "A regular expression that specifies the set of benchmarks "
60*58b9f456SAndroid Build Coastguard Worker "to execute. If this flag is empty, or if this flag is the "
61*58b9f456SAndroid Build Coastguard Worker "string \"all\", all benchmarks linked into the binary are "
62*58b9f456SAndroid Build Coastguard Worker "run.");
63*58b9f456SAndroid Build Coastguard Worker
64*58b9f456SAndroid Build Coastguard Worker DEFINE_double(benchmark_min_time, 0.5,
65*58b9f456SAndroid Build Coastguard Worker "Minimum number of seconds we should run benchmark before "
66*58b9f456SAndroid Build Coastguard Worker "results are considered significant. For cpu-time based "
67*58b9f456SAndroid Build Coastguard Worker "tests, this is the lower bound on the total cpu time "
68*58b9f456SAndroid Build Coastguard Worker "used by all threads that make up the test. For real-time "
69*58b9f456SAndroid Build Coastguard Worker "based tests, this is the lower bound on the elapsed time "
70*58b9f456SAndroid Build Coastguard Worker "of the benchmark execution, regardless of number of "
71*58b9f456SAndroid Build Coastguard Worker "threads.");
72*58b9f456SAndroid Build Coastguard Worker
73*58b9f456SAndroid Build Coastguard Worker DEFINE_int32(benchmark_repetitions, 1,
74*58b9f456SAndroid Build Coastguard Worker "The number of runs of each benchmark. If greater than 1, the "
75*58b9f456SAndroid Build Coastguard Worker "mean and standard deviation of the runs will be reported.");
76*58b9f456SAndroid Build Coastguard Worker
77*58b9f456SAndroid Build Coastguard Worker DEFINE_bool(
78*58b9f456SAndroid Build Coastguard Worker benchmark_report_aggregates_only, false,
79*58b9f456SAndroid Build Coastguard Worker "Report the result of each benchmark repetitions. When 'true' is specified "
80*58b9f456SAndroid Build Coastguard Worker "only the mean, standard deviation, and other statistics are reported for "
81*58b9f456SAndroid Build Coastguard Worker "repeated benchmarks. Affects all reporters.");
82*58b9f456SAndroid Build Coastguard Worker
83*58b9f456SAndroid Build Coastguard Worker DEFINE_bool(
84*58b9f456SAndroid Build Coastguard Worker benchmark_display_aggregates_only, false,
85*58b9f456SAndroid Build Coastguard Worker "Display the result of each benchmark repetitions. When 'true' is "
86*58b9f456SAndroid Build Coastguard Worker "specified only the mean, standard deviation, and other statistics are "
87*58b9f456SAndroid Build Coastguard Worker "displayed for repeated benchmarks. Unlike "
88*58b9f456SAndroid Build Coastguard Worker "benchmark_report_aggregates_only, only affects the display reporter, but "
89*58b9f456SAndroid Build Coastguard Worker "*NOT* file reporter, which will still contain all the output.");
90*58b9f456SAndroid Build Coastguard Worker
91*58b9f456SAndroid Build Coastguard Worker DEFINE_string(benchmark_format, "console",
92*58b9f456SAndroid Build Coastguard Worker "The format to use for console output. Valid values are "
93*58b9f456SAndroid Build Coastguard Worker "'console', 'json', or 'csv'.");
94*58b9f456SAndroid Build Coastguard Worker
95*58b9f456SAndroid Build Coastguard Worker DEFINE_string(benchmark_out_format, "json",
96*58b9f456SAndroid Build Coastguard Worker "The format to use for file output. Valid values are "
97*58b9f456SAndroid Build Coastguard Worker "'console', 'json', or 'csv'.");
98*58b9f456SAndroid Build Coastguard Worker
99*58b9f456SAndroid Build Coastguard Worker DEFINE_string(benchmark_out, "", "The file to write additional output to");
100*58b9f456SAndroid Build Coastguard Worker
101*58b9f456SAndroid Build Coastguard Worker DEFINE_string(benchmark_color, "auto",
102*58b9f456SAndroid Build Coastguard Worker "Whether to use colors in the output. Valid values: "
103*58b9f456SAndroid Build Coastguard Worker "'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use "
104*58b9f456SAndroid Build Coastguard Worker "colors if the output is being sent to a terminal and the TERM "
105*58b9f456SAndroid Build Coastguard Worker "environment variable is set to a terminal type that supports "
106*58b9f456SAndroid Build Coastguard Worker "colors.");
107*58b9f456SAndroid Build Coastguard Worker
108*58b9f456SAndroid Build Coastguard Worker DEFINE_bool(benchmark_counters_tabular, false,
109*58b9f456SAndroid Build Coastguard Worker "Whether to use tabular format when printing user counters to "
110*58b9f456SAndroid Build Coastguard Worker "the console. Valid values: 'true'/'yes'/1, 'false'/'no'/0."
111*58b9f456SAndroid Build Coastguard Worker "Defaults to false.");
112*58b9f456SAndroid Build Coastguard Worker
113*58b9f456SAndroid Build Coastguard Worker DEFINE_int32(v, 0, "The level of verbose logging to output");
114*58b9f456SAndroid Build Coastguard Worker
115*58b9f456SAndroid Build Coastguard Worker namespace benchmark {
116*58b9f456SAndroid Build Coastguard Worker
117*58b9f456SAndroid Build Coastguard Worker namespace internal {
118*58b9f456SAndroid Build Coastguard Worker
119*58b9f456SAndroid Build Coastguard Worker // FIXME: wouldn't LTO mess this up?
UseCharPointer(char const volatile *)120*58b9f456SAndroid Build Coastguard Worker void UseCharPointer(char const volatile*) {}
121*58b9f456SAndroid Build Coastguard Worker
122*58b9f456SAndroid Build Coastguard Worker } // namespace internal
123*58b9f456SAndroid Build Coastguard Worker
State(size_t max_iters,const std::vector<int64_t> & ranges,int thread_i,int n_threads,internal::ThreadTimer * timer,internal::ThreadManager * manager)124*58b9f456SAndroid Build Coastguard Worker State::State(size_t max_iters, const std::vector<int64_t>& ranges, int thread_i,
125*58b9f456SAndroid Build Coastguard Worker int n_threads, internal::ThreadTimer* timer,
126*58b9f456SAndroid Build Coastguard Worker internal::ThreadManager* manager)
127*58b9f456SAndroid Build Coastguard Worker : total_iterations_(0),
128*58b9f456SAndroid Build Coastguard Worker batch_leftover_(0),
129*58b9f456SAndroid Build Coastguard Worker max_iterations(max_iters),
130*58b9f456SAndroid Build Coastguard Worker started_(false),
131*58b9f456SAndroid Build Coastguard Worker finished_(false),
132*58b9f456SAndroid Build Coastguard Worker error_occurred_(false),
133*58b9f456SAndroid Build Coastguard Worker range_(ranges),
134*58b9f456SAndroid Build Coastguard Worker complexity_n_(0),
135*58b9f456SAndroid Build Coastguard Worker counters(),
136*58b9f456SAndroid Build Coastguard Worker thread_index(thread_i),
137*58b9f456SAndroid Build Coastguard Worker threads(n_threads),
138*58b9f456SAndroid Build Coastguard Worker timer_(timer),
139*58b9f456SAndroid Build Coastguard Worker manager_(manager) {
140*58b9f456SAndroid Build Coastguard Worker CHECK(max_iterations != 0) << "At least one iteration must be run";
141*58b9f456SAndroid Build Coastguard Worker CHECK_LT(thread_index, threads) << "thread_index must be less than threads";
142*58b9f456SAndroid Build Coastguard Worker
143*58b9f456SAndroid Build Coastguard Worker // Note: The use of offsetof below is technically undefined until C++17
144*58b9f456SAndroid Build Coastguard Worker // because State is not a standard layout type. However, all compilers
145*58b9f456SAndroid Build Coastguard Worker // currently provide well-defined behavior as an extension (which is
146*58b9f456SAndroid Build Coastguard Worker // demonstrated since constexpr evaluation must diagnose all undefined
147*58b9f456SAndroid Build Coastguard Worker // behavior). However, GCC and Clang also warn about this use of offsetof,
148*58b9f456SAndroid Build Coastguard Worker // which must be suppressed.
149*58b9f456SAndroid Build Coastguard Worker #if defined(__INTEL_COMPILER)
150*58b9f456SAndroid Build Coastguard Worker #pragma warning push
151*58b9f456SAndroid Build Coastguard Worker #pragma warning(disable:1875)
152*58b9f456SAndroid Build Coastguard Worker #elif defined(__GNUC__)
153*58b9f456SAndroid Build Coastguard Worker #pragma GCC diagnostic push
154*58b9f456SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Winvalid-offsetof"
155*58b9f456SAndroid Build Coastguard Worker #endif
156*58b9f456SAndroid Build Coastguard Worker // Offset tests to ensure commonly accessed data is on the first cache line.
157*58b9f456SAndroid Build Coastguard Worker const int cache_line_size = 64;
158*58b9f456SAndroid Build Coastguard Worker static_assert(offsetof(State, error_occurred_) <=
159*58b9f456SAndroid Build Coastguard Worker (cache_line_size - sizeof(error_occurred_)),
160*58b9f456SAndroid Build Coastguard Worker "");
161*58b9f456SAndroid Build Coastguard Worker #if defined(__INTEL_COMPILER)
162*58b9f456SAndroid Build Coastguard Worker #pragma warning pop
163*58b9f456SAndroid Build Coastguard Worker #elif defined(__GNUC__)
164*58b9f456SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
165*58b9f456SAndroid Build Coastguard Worker #endif
166*58b9f456SAndroid Build Coastguard Worker }
167*58b9f456SAndroid Build Coastguard Worker
PauseTiming()168*58b9f456SAndroid Build Coastguard Worker void State::PauseTiming() {
169*58b9f456SAndroid Build Coastguard Worker // Add in time accumulated so far
170*58b9f456SAndroid Build Coastguard Worker CHECK(started_ && !finished_ && !error_occurred_);
171*58b9f456SAndroid Build Coastguard Worker timer_->StopTimer();
172*58b9f456SAndroid Build Coastguard Worker }
173*58b9f456SAndroid Build Coastguard Worker
ResumeTiming()174*58b9f456SAndroid Build Coastguard Worker void State::ResumeTiming() {
175*58b9f456SAndroid Build Coastguard Worker CHECK(started_ && !finished_ && !error_occurred_);
176*58b9f456SAndroid Build Coastguard Worker timer_->StartTimer();
177*58b9f456SAndroid Build Coastguard Worker }
178*58b9f456SAndroid Build Coastguard Worker
SkipWithError(const char * msg)179*58b9f456SAndroid Build Coastguard Worker void State::SkipWithError(const char* msg) {
180*58b9f456SAndroid Build Coastguard Worker CHECK(msg);
181*58b9f456SAndroid Build Coastguard Worker error_occurred_ = true;
182*58b9f456SAndroid Build Coastguard Worker {
183*58b9f456SAndroid Build Coastguard Worker MutexLock l(manager_->GetBenchmarkMutex());
184*58b9f456SAndroid Build Coastguard Worker if (manager_->results.has_error_ == false) {
185*58b9f456SAndroid Build Coastguard Worker manager_->results.error_message_ = msg;
186*58b9f456SAndroid Build Coastguard Worker manager_->results.has_error_ = true;
187*58b9f456SAndroid Build Coastguard Worker }
188*58b9f456SAndroid Build Coastguard Worker }
189*58b9f456SAndroid Build Coastguard Worker total_iterations_ = 0;
190*58b9f456SAndroid Build Coastguard Worker if (timer_->running()) timer_->StopTimer();
191*58b9f456SAndroid Build Coastguard Worker }
192*58b9f456SAndroid Build Coastguard Worker
SetIterationTime(double seconds)193*58b9f456SAndroid Build Coastguard Worker void State::SetIterationTime(double seconds) {
194*58b9f456SAndroid Build Coastguard Worker timer_->SetIterationTime(seconds);
195*58b9f456SAndroid Build Coastguard Worker }
196*58b9f456SAndroid Build Coastguard Worker
SetLabel(const char * label)197*58b9f456SAndroid Build Coastguard Worker void State::SetLabel(const char* label) {
198*58b9f456SAndroid Build Coastguard Worker MutexLock l(manager_->GetBenchmarkMutex());
199*58b9f456SAndroid Build Coastguard Worker manager_->results.report_label_ = label;
200*58b9f456SAndroid Build Coastguard Worker }
201*58b9f456SAndroid Build Coastguard Worker
StartKeepRunning()202*58b9f456SAndroid Build Coastguard Worker void State::StartKeepRunning() {
203*58b9f456SAndroid Build Coastguard Worker CHECK(!started_ && !finished_);
204*58b9f456SAndroid Build Coastguard Worker started_ = true;
205*58b9f456SAndroid Build Coastguard Worker total_iterations_ = error_occurred_ ? 0 : max_iterations;
206*58b9f456SAndroid Build Coastguard Worker manager_->StartStopBarrier();
207*58b9f456SAndroid Build Coastguard Worker if (!error_occurred_) ResumeTiming();
208*58b9f456SAndroid Build Coastguard Worker }
209*58b9f456SAndroid Build Coastguard Worker
FinishKeepRunning()210*58b9f456SAndroid Build Coastguard Worker void State::FinishKeepRunning() {
211*58b9f456SAndroid Build Coastguard Worker CHECK(started_ && (!finished_ || error_occurred_));
212*58b9f456SAndroid Build Coastguard Worker if (!error_occurred_) {
213*58b9f456SAndroid Build Coastguard Worker PauseTiming();
214*58b9f456SAndroid Build Coastguard Worker }
215*58b9f456SAndroid Build Coastguard Worker // Total iterations has now wrapped around past 0. Fix this.
216*58b9f456SAndroid Build Coastguard Worker total_iterations_ = 0;
217*58b9f456SAndroid Build Coastguard Worker finished_ = true;
218*58b9f456SAndroid Build Coastguard Worker manager_->StartStopBarrier();
219*58b9f456SAndroid Build Coastguard Worker }
220*58b9f456SAndroid Build Coastguard Worker
221*58b9f456SAndroid Build Coastguard Worker namespace internal {
222*58b9f456SAndroid Build Coastguard Worker namespace {
223*58b9f456SAndroid Build Coastguard Worker
RunBenchmarks(const std::vector<BenchmarkInstance> & benchmarks,BenchmarkReporter * display_reporter,BenchmarkReporter * file_reporter)224*58b9f456SAndroid Build Coastguard Worker void RunBenchmarks(const std::vector<BenchmarkInstance>& benchmarks,
225*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter* display_reporter,
226*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter* file_reporter) {
227*58b9f456SAndroid Build Coastguard Worker // Note the file_reporter can be null.
228*58b9f456SAndroid Build Coastguard Worker CHECK(display_reporter != nullptr);
229*58b9f456SAndroid Build Coastguard Worker
230*58b9f456SAndroid Build Coastguard Worker // Determine the width of the name field using a minimum width of 10.
231*58b9f456SAndroid Build Coastguard Worker bool might_have_aggregates = FLAGS_benchmark_repetitions > 1;
232*58b9f456SAndroid Build Coastguard Worker size_t name_field_width = 10;
233*58b9f456SAndroid Build Coastguard Worker size_t stat_field_width = 0;
234*58b9f456SAndroid Build Coastguard Worker for (const BenchmarkInstance& benchmark : benchmarks) {
235*58b9f456SAndroid Build Coastguard Worker name_field_width =
236*58b9f456SAndroid Build Coastguard Worker std::max<size_t>(name_field_width, benchmark.name.size());
237*58b9f456SAndroid Build Coastguard Worker might_have_aggregates |= benchmark.repetitions > 1;
238*58b9f456SAndroid Build Coastguard Worker
239*58b9f456SAndroid Build Coastguard Worker for (const auto& Stat : *benchmark.statistics)
240*58b9f456SAndroid Build Coastguard Worker stat_field_width = std::max<size_t>(stat_field_width, Stat.name_.size());
241*58b9f456SAndroid Build Coastguard Worker }
242*58b9f456SAndroid Build Coastguard Worker if (might_have_aggregates) name_field_width += 1 + stat_field_width;
243*58b9f456SAndroid Build Coastguard Worker
244*58b9f456SAndroid Build Coastguard Worker // Print header here
245*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter::Context context;
246*58b9f456SAndroid Build Coastguard Worker context.name_field_width = name_field_width;
247*58b9f456SAndroid Build Coastguard Worker
248*58b9f456SAndroid Build Coastguard Worker // Keep track of running times of all instances of current benchmark
249*58b9f456SAndroid Build Coastguard Worker std::vector<BenchmarkReporter::Run> complexity_reports;
250*58b9f456SAndroid Build Coastguard Worker
251*58b9f456SAndroid Build Coastguard Worker // We flush streams after invoking reporter methods that write to them. This
252*58b9f456SAndroid Build Coastguard Worker // ensures users get timely updates even when streams are not line-buffered.
253*58b9f456SAndroid Build Coastguard Worker auto flushStreams = [](BenchmarkReporter* reporter) {
254*58b9f456SAndroid Build Coastguard Worker if (!reporter) return;
255*58b9f456SAndroid Build Coastguard Worker std::flush(reporter->GetOutputStream());
256*58b9f456SAndroid Build Coastguard Worker std::flush(reporter->GetErrorStream());
257*58b9f456SAndroid Build Coastguard Worker };
258*58b9f456SAndroid Build Coastguard Worker
259*58b9f456SAndroid Build Coastguard Worker if (display_reporter->ReportContext(context) &&
260*58b9f456SAndroid Build Coastguard Worker (!file_reporter || file_reporter->ReportContext(context))) {
261*58b9f456SAndroid Build Coastguard Worker flushStreams(display_reporter);
262*58b9f456SAndroid Build Coastguard Worker flushStreams(file_reporter);
263*58b9f456SAndroid Build Coastguard Worker
264*58b9f456SAndroid Build Coastguard Worker for (const auto& benchmark : benchmarks) {
265*58b9f456SAndroid Build Coastguard Worker RunResults run_results = RunBenchmark(benchmark, &complexity_reports);
266*58b9f456SAndroid Build Coastguard Worker
267*58b9f456SAndroid Build Coastguard Worker auto report = [&run_results](BenchmarkReporter* reporter,
268*58b9f456SAndroid Build Coastguard Worker bool report_aggregates_only) {
269*58b9f456SAndroid Build Coastguard Worker assert(reporter);
270*58b9f456SAndroid Build Coastguard Worker // If there are no aggregates, do output non-aggregates.
271*58b9f456SAndroid Build Coastguard Worker report_aggregates_only &= !run_results.aggregates_only.empty();
272*58b9f456SAndroid Build Coastguard Worker if (!report_aggregates_only)
273*58b9f456SAndroid Build Coastguard Worker reporter->ReportRuns(run_results.non_aggregates);
274*58b9f456SAndroid Build Coastguard Worker if (!run_results.aggregates_only.empty())
275*58b9f456SAndroid Build Coastguard Worker reporter->ReportRuns(run_results.aggregates_only);
276*58b9f456SAndroid Build Coastguard Worker };
277*58b9f456SAndroid Build Coastguard Worker
278*58b9f456SAndroid Build Coastguard Worker report(display_reporter, run_results.display_report_aggregates_only);
279*58b9f456SAndroid Build Coastguard Worker if (file_reporter)
280*58b9f456SAndroid Build Coastguard Worker report(file_reporter, run_results.file_report_aggregates_only);
281*58b9f456SAndroid Build Coastguard Worker
282*58b9f456SAndroid Build Coastguard Worker flushStreams(display_reporter);
283*58b9f456SAndroid Build Coastguard Worker flushStreams(file_reporter);
284*58b9f456SAndroid Build Coastguard Worker }
285*58b9f456SAndroid Build Coastguard Worker }
286*58b9f456SAndroid Build Coastguard Worker display_reporter->Finalize();
287*58b9f456SAndroid Build Coastguard Worker if (file_reporter) file_reporter->Finalize();
288*58b9f456SAndroid Build Coastguard Worker flushStreams(display_reporter);
289*58b9f456SAndroid Build Coastguard Worker flushStreams(file_reporter);
290*58b9f456SAndroid Build Coastguard Worker }
291*58b9f456SAndroid Build Coastguard Worker
CreateReporter(std::string const & name,ConsoleReporter::OutputOptions output_opts)292*58b9f456SAndroid Build Coastguard Worker std::unique_ptr<BenchmarkReporter> CreateReporter(
293*58b9f456SAndroid Build Coastguard Worker std::string const& name, ConsoleReporter::OutputOptions output_opts) {
294*58b9f456SAndroid Build Coastguard Worker typedef std::unique_ptr<BenchmarkReporter> PtrType;
295*58b9f456SAndroid Build Coastguard Worker if (name == "console") {
296*58b9f456SAndroid Build Coastguard Worker return PtrType(new ConsoleReporter(output_opts));
297*58b9f456SAndroid Build Coastguard Worker } else if (name == "json") {
298*58b9f456SAndroid Build Coastguard Worker return PtrType(new JSONReporter);
299*58b9f456SAndroid Build Coastguard Worker } else if (name == "csv") {
300*58b9f456SAndroid Build Coastguard Worker return PtrType(new CSVReporter);
301*58b9f456SAndroid Build Coastguard Worker } else {
302*58b9f456SAndroid Build Coastguard Worker std::cerr << "Unexpected format: '" << name << "'\n";
303*58b9f456SAndroid Build Coastguard Worker std::exit(1);
304*58b9f456SAndroid Build Coastguard Worker }
305*58b9f456SAndroid Build Coastguard Worker }
306*58b9f456SAndroid Build Coastguard Worker
307*58b9f456SAndroid Build Coastguard Worker } // end namespace
308*58b9f456SAndroid Build Coastguard Worker
IsZero(double n)309*58b9f456SAndroid Build Coastguard Worker bool IsZero(double n) {
310*58b9f456SAndroid Build Coastguard Worker return std::abs(n) < std::numeric_limits<double>::epsilon();
311*58b9f456SAndroid Build Coastguard Worker }
312*58b9f456SAndroid Build Coastguard Worker
GetOutputOptions(bool force_no_color)313*58b9f456SAndroid Build Coastguard Worker ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
314*58b9f456SAndroid Build Coastguard Worker int output_opts = ConsoleReporter::OO_Defaults;
315*58b9f456SAndroid Build Coastguard Worker auto is_benchmark_color = [force_no_color] () -> bool {
316*58b9f456SAndroid Build Coastguard Worker if (force_no_color) {
317*58b9f456SAndroid Build Coastguard Worker return false;
318*58b9f456SAndroid Build Coastguard Worker }
319*58b9f456SAndroid Build Coastguard Worker if (FLAGS_benchmark_color == "auto") {
320*58b9f456SAndroid Build Coastguard Worker return IsColorTerminal();
321*58b9f456SAndroid Build Coastguard Worker }
322*58b9f456SAndroid Build Coastguard Worker return IsTruthyFlagValue(FLAGS_benchmark_color);
323*58b9f456SAndroid Build Coastguard Worker };
324*58b9f456SAndroid Build Coastguard Worker if (is_benchmark_color()) {
325*58b9f456SAndroid Build Coastguard Worker output_opts |= ConsoleReporter::OO_Color;
326*58b9f456SAndroid Build Coastguard Worker } else {
327*58b9f456SAndroid Build Coastguard Worker output_opts &= ~ConsoleReporter::OO_Color;
328*58b9f456SAndroid Build Coastguard Worker }
329*58b9f456SAndroid Build Coastguard Worker if (FLAGS_benchmark_counters_tabular) {
330*58b9f456SAndroid Build Coastguard Worker output_opts |= ConsoleReporter::OO_Tabular;
331*58b9f456SAndroid Build Coastguard Worker } else {
332*58b9f456SAndroid Build Coastguard Worker output_opts &= ~ConsoleReporter::OO_Tabular;
333*58b9f456SAndroid Build Coastguard Worker }
334*58b9f456SAndroid Build Coastguard Worker return static_cast<ConsoleReporter::OutputOptions>(output_opts);
335*58b9f456SAndroid Build Coastguard Worker }
336*58b9f456SAndroid Build Coastguard Worker
337*58b9f456SAndroid Build Coastguard Worker } // end namespace internal
338*58b9f456SAndroid Build Coastguard Worker
RunSpecifiedBenchmarks()339*58b9f456SAndroid Build Coastguard Worker size_t RunSpecifiedBenchmarks() {
340*58b9f456SAndroid Build Coastguard Worker return RunSpecifiedBenchmarks(nullptr, nullptr);
341*58b9f456SAndroid Build Coastguard Worker }
342*58b9f456SAndroid Build Coastguard Worker
RunSpecifiedBenchmarks(BenchmarkReporter * display_reporter)343*58b9f456SAndroid Build Coastguard Worker size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter) {
344*58b9f456SAndroid Build Coastguard Worker return RunSpecifiedBenchmarks(display_reporter, nullptr);
345*58b9f456SAndroid Build Coastguard Worker }
346*58b9f456SAndroid Build Coastguard Worker
RunSpecifiedBenchmarks(BenchmarkReporter * display_reporter,BenchmarkReporter * file_reporter)347*58b9f456SAndroid Build Coastguard Worker size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
348*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter* file_reporter) {
349*58b9f456SAndroid Build Coastguard Worker std::string spec = FLAGS_benchmark_filter;
350*58b9f456SAndroid Build Coastguard Worker if (spec.empty() || spec == "all")
351*58b9f456SAndroid Build Coastguard Worker spec = "."; // Regexp that matches all benchmarks
352*58b9f456SAndroid Build Coastguard Worker
353*58b9f456SAndroid Build Coastguard Worker // Setup the reporters
354*58b9f456SAndroid Build Coastguard Worker std::ofstream output_file;
355*58b9f456SAndroid Build Coastguard Worker std::unique_ptr<BenchmarkReporter> default_display_reporter;
356*58b9f456SAndroid Build Coastguard Worker std::unique_ptr<BenchmarkReporter> default_file_reporter;
357*58b9f456SAndroid Build Coastguard Worker if (!display_reporter) {
358*58b9f456SAndroid Build Coastguard Worker default_display_reporter = internal::CreateReporter(
359*58b9f456SAndroid Build Coastguard Worker FLAGS_benchmark_format, internal::GetOutputOptions());
360*58b9f456SAndroid Build Coastguard Worker display_reporter = default_display_reporter.get();
361*58b9f456SAndroid Build Coastguard Worker }
362*58b9f456SAndroid Build Coastguard Worker auto& Out = display_reporter->GetOutputStream();
363*58b9f456SAndroid Build Coastguard Worker auto& Err = display_reporter->GetErrorStream();
364*58b9f456SAndroid Build Coastguard Worker
365*58b9f456SAndroid Build Coastguard Worker std::string const& fname = FLAGS_benchmark_out;
366*58b9f456SAndroid Build Coastguard Worker if (fname.empty() && file_reporter) {
367*58b9f456SAndroid Build Coastguard Worker Err << "A custom file reporter was provided but "
368*58b9f456SAndroid Build Coastguard Worker "--benchmark_out=<file> was not specified."
369*58b9f456SAndroid Build Coastguard Worker << std::endl;
370*58b9f456SAndroid Build Coastguard Worker std::exit(1);
371*58b9f456SAndroid Build Coastguard Worker }
372*58b9f456SAndroid Build Coastguard Worker if (!fname.empty()) {
373*58b9f456SAndroid Build Coastguard Worker output_file.open(fname);
374*58b9f456SAndroid Build Coastguard Worker if (!output_file.is_open()) {
375*58b9f456SAndroid Build Coastguard Worker Err << "invalid file name: '" << fname << std::endl;
376*58b9f456SAndroid Build Coastguard Worker std::exit(1);
377*58b9f456SAndroid Build Coastguard Worker }
378*58b9f456SAndroid Build Coastguard Worker if (!file_reporter) {
379*58b9f456SAndroid Build Coastguard Worker default_file_reporter = internal::CreateReporter(
380*58b9f456SAndroid Build Coastguard Worker FLAGS_benchmark_out_format, ConsoleReporter::OO_None);
381*58b9f456SAndroid Build Coastguard Worker file_reporter = default_file_reporter.get();
382*58b9f456SAndroid Build Coastguard Worker }
383*58b9f456SAndroid Build Coastguard Worker file_reporter->SetOutputStream(&output_file);
384*58b9f456SAndroid Build Coastguard Worker file_reporter->SetErrorStream(&output_file);
385*58b9f456SAndroid Build Coastguard Worker }
386*58b9f456SAndroid Build Coastguard Worker
387*58b9f456SAndroid Build Coastguard Worker std::vector<internal::BenchmarkInstance> benchmarks;
388*58b9f456SAndroid Build Coastguard Worker if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) return 0;
389*58b9f456SAndroid Build Coastguard Worker
390*58b9f456SAndroid Build Coastguard Worker if (benchmarks.empty()) {
391*58b9f456SAndroid Build Coastguard Worker Err << "Failed to match any benchmarks against regex: " << spec << "\n";
392*58b9f456SAndroid Build Coastguard Worker return 0;
393*58b9f456SAndroid Build Coastguard Worker }
394*58b9f456SAndroid Build Coastguard Worker
395*58b9f456SAndroid Build Coastguard Worker if (FLAGS_benchmark_list_tests) {
396*58b9f456SAndroid Build Coastguard Worker for (auto const& benchmark : benchmarks) Out << benchmark.name << "\n";
397*58b9f456SAndroid Build Coastguard Worker } else {
398*58b9f456SAndroid Build Coastguard Worker internal::RunBenchmarks(benchmarks, display_reporter, file_reporter);
399*58b9f456SAndroid Build Coastguard Worker }
400*58b9f456SAndroid Build Coastguard Worker
401*58b9f456SAndroid Build Coastguard Worker return benchmarks.size();
402*58b9f456SAndroid Build Coastguard Worker }
403*58b9f456SAndroid Build Coastguard Worker
RegisterMemoryManager(MemoryManager * manager)404*58b9f456SAndroid Build Coastguard Worker void RegisterMemoryManager(MemoryManager* manager) {
405*58b9f456SAndroid Build Coastguard Worker internal::memory_manager = manager;
406*58b9f456SAndroid Build Coastguard Worker }
407*58b9f456SAndroid Build Coastguard Worker
408*58b9f456SAndroid Build Coastguard Worker namespace internal {
409*58b9f456SAndroid Build Coastguard Worker
PrintUsageAndExit()410*58b9f456SAndroid Build Coastguard Worker void PrintUsageAndExit() {
411*58b9f456SAndroid Build Coastguard Worker fprintf(stdout,
412*58b9f456SAndroid Build Coastguard Worker "benchmark"
413*58b9f456SAndroid Build Coastguard Worker " [--benchmark_list_tests={true|false}]\n"
414*58b9f456SAndroid Build Coastguard Worker " [--benchmark_filter=<regex>]\n"
415*58b9f456SAndroid Build Coastguard Worker " [--benchmark_min_time=<min_time>]\n"
416*58b9f456SAndroid Build Coastguard Worker " [--benchmark_repetitions=<num_repetitions>]\n"
417*58b9f456SAndroid Build Coastguard Worker " [--benchmark_report_aggregates_only={true|false}]\n"
418*58b9f456SAndroid Build Coastguard Worker " [--benchmark_display_aggregates_only={true|false}]\n"
419*58b9f456SAndroid Build Coastguard Worker " [--benchmark_format=<console|json|csv>]\n"
420*58b9f456SAndroid Build Coastguard Worker " [--benchmark_out=<filename>]\n"
421*58b9f456SAndroid Build Coastguard Worker " [--benchmark_out_format=<json|console|csv>]\n"
422*58b9f456SAndroid Build Coastguard Worker " [--benchmark_color={auto|true|false}]\n"
423*58b9f456SAndroid Build Coastguard Worker " [--benchmark_counters_tabular={true|false}]\n"
424*58b9f456SAndroid Build Coastguard Worker " [--v=<verbosity>]\n");
425*58b9f456SAndroid Build Coastguard Worker exit(0);
426*58b9f456SAndroid Build Coastguard Worker }
427*58b9f456SAndroid Build Coastguard Worker
ParseCommandLineFlags(int * argc,char ** argv)428*58b9f456SAndroid Build Coastguard Worker void ParseCommandLineFlags(int* argc, char** argv) {
429*58b9f456SAndroid Build Coastguard Worker using namespace benchmark;
430*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter::Context::executable_name =
431*58b9f456SAndroid Build Coastguard Worker (argc && *argc > 0) ? argv[0] : "unknown";
432*58b9f456SAndroid Build Coastguard Worker for (int i = 1; i < *argc; ++i) {
433*58b9f456SAndroid Build Coastguard Worker if (ParseBoolFlag(argv[i], "benchmark_list_tests",
434*58b9f456SAndroid Build Coastguard Worker &FLAGS_benchmark_list_tests) ||
435*58b9f456SAndroid Build Coastguard Worker ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) ||
436*58b9f456SAndroid Build Coastguard Worker ParseDoubleFlag(argv[i], "benchmark_min_time",
437*58b9f456SAndroid Build Coastguard Worker &FLAGS_benchmark_min_time) ||
438*58b9f456SAndroid Build Coastguard Worker ParseInt32Flag(argv[i], "benchmark_repetitions",
439*58b9f456SAndroid Build Coastguard Worker &FLAGS_benchmark_repetitions) ||
440*58b9f456SAndroid Build Coastguard Worker ParseBoolFlag(argv[i], "benchmark_report_aggregates_only",
441*58b9f456SAndroid Build Coastguard Worker &FLAGS_benchmark_report_aggregates_only) ||
442*58b9f456SAndroid Build Coastguard Worker ParseBoolFlag(argv[i], "benchmark_display_aggregates_only",
443*58b9f456SAndroid Build Coastguard Worker &FLAGS_benchmark_display_aggregates_only) ||
444*58b9f456SAndroid Build Coastguard Worker ParseStringFlag(argv[i], "benchmark_format", &FLAGS_benchmark_format) ||
445*58b9f456SAndroid Build Coastguard Worker ParseStringFlag(argv[i], "benchmark_out", &FLAGS_benchmark_out) ||
446*58b9f456SAndroid Build Coastguard Worker ParseStringFlag(argv[i], "benchmark_out_format",
447*58b9f456SAndroid Build Coastguard Worker &FLAGS_benchmark_out_format) ||
448*58b9f456SAndroid Build Coastguard Worker ParseStringFlag(argv[i], "benchmark_color", &FLAGS_benchmark_color) ||
449*58b9f456SAndroid Build Coastguard Worker // "color_print" is the deprecated name for "benchmark_color".
450*58b9f456SAndroid Build Coastguard Worker // TODO: Remove this.
451*58b9f456SAndroid Build Coastguard Worker ParseStringFlag(argv[i], "color_print", &FLAGS_benchmark_color) ||
452*58b9f456SAndroid Build Coastguard Worker ParseBoolFlag(argv[i], "benchmark_counters_tabular",
453*58b9f456SAndroid Build Coastguard Worker &FLAGS_benchmark_counters_tabular) ||
454*58b9f456SAndroid Build Coastguard Worker ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
455*58b9f456SAndroid Build Coastguard Worker for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1];
456*58b9f456SAndroid Build Coastguard Worker
457*58b9f456SAndroid Build Coastguard Worker --(*argc);
458*58b9f456SAndroid Build Coastguard Worker --i;
459*58b9f456SAndroid Build Coastguard Worker } else if (IsFlag(argv[i], "help")) {
460*58b9f456SAndroid Build Coastguard Worker PrintUsageAndExit();
461*58b9f456SAndroid Build Coastguard Worker }
462*58b9f456SAndroid Build Coastguard Worker }
463*58b9f456SAndroid Build Coastguard Worker for (auto const* flag :
464*58b9f456SAndroid Build Coastguard Worker {&FLAGS_benchmark_format, &FLAGS_benchmark_out_format})
465*58b9f456SAndroid Build Coastguard Worker if (*flag != "console" && *flag != "json" && *flag != "csv") {
466*58b9f456SAndroid Build Coastguard Worker PrintUsageAndExit();
467*58b9f456SAndroid Build Coastguard Worker }
468*58b9f456SAndroid Build Coastguard Worker if (FLAGS_benchmark_color.empty()) {
469*58b9f456SAndroid Build Coastguard Worker PrintUsageAndExit();
470*58b9f456SAndroid Build Coastguard Worker }
471*58b9f456SAndroid Build Coastguard Worker }
472*58b9f456SAndroid Build Coastguard Worker
InitializeStreams()473*58b9f456SAndroid Build Coastguard Worker int InitializeStreams() {
474*58b9f456SAndroid Build Coastguard Worker static std::ios_base::Init init;
475*58b9f456SAndroid Build Coastguard Worker return 0;
476*58b9f456SAndroid Build Coastguard Worker }
477*58b9f456SAndroid Build Coastguard Worker
478*58b9f456SAndroid Build Coastguard Worker } // end namespace internal
479*58b9f456SAndroid Build Coastguard Worker
Initialize(int * argc,char ** argv)480*58b9f456SAndroid Build Coastguard Worker void Initialize(int* argc, char** argv) {
481*58b9f456SAndroid Build Coastguard Worker internal::ParseCommandLineFlags(argc, argv);
482*58b9f456SAndroid Build Coastguard Worker internal::LogLevel() = FLAGS_v;
483*58b9f456SAndroid Build Coastguard Worker }
484*58b9f456SAndroid Build Coastguard Worker
ReportUnrecognizedArguments(int argc,char ** argv)485*58b9f456SAndroid Build Coastguard Worker bool ReportUnrecognizedArguments(int argc, char** argv) {
486*58b9f456SAndroid Build Coastguard Worker for (int i = 1; i < argc; ++i) {
487*58b9f456SAndroid Build Coastguard Worker fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0],
488*58b9f456SAndroid Build Coastguard Worker argv[i]);
489*58b9f456SAndroid Build Coastguard Worker }
490*58b9f456SAndroid Build Coastguard Worker return argc > 1;
491*58b9f456SAndroid Build Coastguard Worker }
492*58b9f456SAndroid Build Coastguard Worker
493*58b9f456SAndroid Build Coastguard Worker } // end namespace benchmark
494