1*dbb99499SAndroid Build Coastguard Worker // Copyright 2015 Google Inc. All rights reserved.
2*dbb99499SAndroid Build Coastguard Worker //
3*dbb99499SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*dbb99499SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*dbb99499SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*dbb99499SAndroid Build Coastguard Worker //
7*dbb99499SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*dbb99499SAndroid Build Coastguard Worker //
9*dbb99499SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*dbb99499SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*dbb99499SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*dbb99499SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*dbb99499SAndroid Build Coastguard Worker // limitations under the License.
14*dbb99499SAndroid Build Coastguard Worker
15*dbb99499SAndroid Build Coastguard Worker #include "benchmark_runner.h"
16*dbb99499SAndroid Build Coastguard Worker
17*dbb99499SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
18*dbb99499SAndroid Build Coastguard Worker #include "benchmark_api_internal.h"
19*dbb99499SAndroid Build Coastguard Worker #include "internal_macros.h"
20*dbb99499SAndroid Build Coastguard Worker
21*dbb99499SAndroid Build Coastguard Worker #ifndef BENCHMARK_OS_WINDOWS
22*dbb99499SAndroid Build Coastguard Worker #if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
23*dbb99499SAndroid Build Coastguard Worker #include <sys/resource.h>
24*dbb99499SAndroid Build Coastguard Worker #endif
25*dbb99499SAndroid Build Coastguard Worker #include <sys/time.h>
26*dbb99499SAndroid Build Coastguard Worker #include <unistd.h>
27*dbb99499SAndroid Build Coastguard Worker #endif
28*dbb99499SAndroid Build Coastguard Worker
29*dbb99499SAndroid Build Coastguard Worker #include <algorithm>
30*dbb99499SAndroid Build Coastguard Worker #include <atomic>
31*dbb99499SAndroid Build Coastguard Worker #include <climits>
32*dbb99499SAndroid Build Coastguard Worker #include <cmath>
33*dbb99499SAndroid Build Coastguard Worker #include <condition_variable>
34*dbb99499SAndroid Build Coastguard Worker #include <cstdio>
35*dbb99499SAndroid Build Coastguard Worker #include <cstdlib>
36*dbb99499SAndroid Build Coastguard Worker #include <fstream>
37*dbb99499SAndroid Build Coastguard Worker #include <iostream>
38*dbb99499SAndroid Build Coastguard Worker #include <limits>
39*dbb99499SAndroid Build Coastguard Worker #include <memory>
40*dbb99499SAndroid Build Coastguard Worker #include <string>
41*dbb99499SAndroid Build Coastguard Worker #include <thread>
42*dbb99499SAndroid Build Coastguard Worker #include <utility>
43*dbb99499SAndroid Build Coastguard Worker
44*dbb99499SAndroid Build Coastguard Worker #include "check.h"
45*dbb99499SAndroid Build Coastguard Worker #include "colorprint.h"
46*dbb99499SAndroid Build Coastguard Worker #include "commandlineflags.h"
47*dbb99499SAndroid Build Coastguard Worker #include "complexity.h"
48*dbb99499SAndroid Build Coastguard Worker #include "counter.h"
49*dbb99499SAndroid Build Coastguard Worker #include "internal_macros.h"
50*dbb99499SAndroid Build Coastguard Worker #include "log.h"
51*dbb99499SAndroid Build Coastguard Worker #include "mutex.h"
52*dbb99499SAndroid Build Coastguard Worker #include "perf_counters.h"
53*dbb99499SAndroid Build Coastguard Worker #include "re.h"
54*dbb99499SAndroid Build Coastguard Worker #include "statistics.h"
55*dbb99499SAndroid Build Coastguard Worker #include "string_util.h"
56*dbb99499SAndroid Build Coastguard Worker #include "thread_manager.h"
57*dbb99499SAndroid Build Coastguard Worker #include "thread_timer.h"
58*dbb99499SAndroid Build Coastguard Worker
59*dbb99499SAndroid Build Coastguard Worker namespace benchmark {
60*dbb99499SAndroid Build Coastguard Worker
61*dbb99499SAndroid Build Coastguard Worker namespace internal {
62*dbb99499SAndroid Build Coastguard Worker
63*dbb99499SAndroid Build Coastguard Worker MemoryManager* memory_manager = nullptr;
64*dbb99499SAndroid Build Coastguard Worker
65*dbb99499SAndroid Build Coastguard Worker ProfilerManager* profiler_manager = nullptr;
66*dbb99499SAndroid Build Coastguard Worker
67*dbb99499SAndroid Build Coastguard Worker namespace {
68*dbb99499SAndroid Build Coastguard Worker
69*dbb99499SAndroid Build Coastguard Worker static constexpr IterationCount kMaxIterations = 1000000000000;
70*dbb99499SAndroid Build Coastguard Worker const double kDefaultMinTime =
71*dbb99499SAndroid Build Coastguard Worker std::strtod(::benchmark::kDefaultMinTimeStr, /*p_end*/ nullptr);
72*dbb99499SAndroid Build Coastguard Worker
CreateRunReport(const benchmark::internal::BenchmarkInstance & b,const internal::ThreadManager::Result & results,IterationCount memory_iterations,const MemoryManager::Result * memory_result,double seconds,int64_t repetition_index,int64_t repeats)73*dbb99499SAndroid Build Coastguard Worker BenchmarkReporter::Run CreateRunReport(
74*dbb99499SAndroid Build Coastguard Worker const benchmark::internal::BenchmarkInstance& b,
75*dbb99499SAndroid Build Coastguard Worker const internal::ThreadManager::Result& results,
76*dbb99499SAndroid Build Coastguard Worker IterationCount memory_iterations,
77*dbb99499SAndroid Build Coastguard Worker const MemoryManager::Result* memory_result, double seconds,
78*dbb99499SAndroid Build Coastguard Worker int64_t repetition_index, int64_t repeats) {
79*dbb99499SAndroid Build Coastguard Worker // Create report about this benchmark run.
80*dbb99499SAndroid Build Coastguard Worker BenchmarkReporter::Run report;
81*dbb99499SAndroid Build Coastguard Worker
82*dbb99499SAndroid Build Coastguard Worker report.run_name = b.name();
83*dbb99499SAndroid Build Coastguard Worker report.family_index = b.family_index();
84*dbb99499SAndroid Build Coastguard Worker report.per_family_instance_index = b.per_family_instance_index();
85*dbb99499SAndroid Build Coastguard Worker report.skipped = results.skipped_;
86*dbb99499SAndroid Build Coastguard Worker report.skip_message = results.skip_message_;
87*dbb99499SAndroid Build Coastguard Worker report.report_label = results.report_label_;
88*dbb99499SAndroid Build Coastguard Worker // This is the total iterations across all threads.
89*dbb99499SAndroid Build Coastguard Worker report.iterations = results.iterations;
90*dbb99499SAndroid Build Coastguard Worker report.time_unit = b.time_unit();
91*dbb99499SAndroid Build Coastguard Worker report.threads = b.threads();
92*dbb99499SAndroid Build Coastguard Worker report.repetition_index = repetition_index;
93*dbb99499SAndroid Build Coastguard Worker report.repetitions = repeats;
94*dbb99499SAndroid Build Coastguard Worker
95*dbb99499SAndroid Build Coastguard Worker if (!report.skipped) {
96*dbb99499SAndroid Build Coastguard Worker if (b.use_manual_time()) {
97*dbb99499SAndroid Build Coastguard Worker report.real_accumulated_time = results.manual_time_used;
98*dbb99499SAndroid Build Coastguard Worker } else {
99*dbb99499SAndroid Build Coastguard Worker report.real_accumulated_time = results.real_time_used;
100*dbb99499SAndroid Build Coastguard Worker }
101*dbb99499SAndroid Build Coastguard Worker report.use_real_time_for_initial_big_o = b.use_manual_time();
102*dbb99499SAndroid Build Coastguard Worker report.cpu_accumulated_time = results.cpu_time_used;
103*dbb99499SAndroid Build Coastguard Worker report.complexity_n = results.complexity_n;
104*dbb99499SAndroid Build Coastguard Worker report.complexity = b.complexity();
105*dbb99499SAndroid Build Coastguard Worker report.complexity_lambda = b.complexity_lambda();
106*dbb99499SAndroid Build Coastguard Worker report.statistics = &b.statistics();
107*dbb99499SAndroid Build Coastguard Worker report.counters = results.counters;
108*dbb99499SAndroid Build Coastguard Worker
109*dbb99499SAndroid Build Coastguard Worker if (memory_iterations > 0) {
110*dbb99499SAndroid Build Coastguard Worker assert(memory_result != nullptr);
111*dbb99499SAndroid Build Coastguard Worker report.memory_result = memory_result;
112*dbb99499SAndroid Build Coastguard Worker report.allocs_per_iter =
113*dbb99499SAndroid Build Coastguard Worker memory_iterations ? static_cast<double>(memory_result->num_allocs) /
114*dbb99499SAndroid Build Coastguard Worker static_cast<double>(memory_iterations)
115*dbb99499SAndroid Build Coastguard Worker : 0;
116*dbb99499SAndroid Build Coastguard Worker }
117*dbb99499SAndroid Build Coastguard Worker
118*dbb99499SAndroid Build Coastguard Worker internal::Finish(&report.counters, results.iterations, seconds,
119*dbb99499SAndroid Build Coastguard Worker b.threads());
120*dbb99499SAndroid Build Coastguard Worker }
121*dbb99499SAndroid Build Coastguard Worker return report;
122*dbb99499SAndroid Build Coastguard Worker }
123*dbb99499SAndroid Build Coastguard Worker
124*dbb99499SAndroid Build Coastguard Worker // Execute one thread of benchmark b for the specified number of iterations.
125*dbb99499SAndroid Build Coastguard Worker // Adds the stats collected for the thread into manager->results.
RunInThread(const BenchmarkInstance * b,IterationCount iters,int thread_id,ThreadManager * manager,PerfCountersMeasurement * perf_counters_measurement,ProfilerManager * profiler_manager)126*dbb99499SAndroid Build Coastguard Worker void RunInThread(const BenchmarkInstance* b, IterationCount iters,
127*dbb99499SAndroid Build Coastguard Worker int thread_id, ThreadManager* manager,
128*dbb99499SAndroid Build Coastguard Worker PerfCountersMeasurement* perf_counters_measurement,
129*dbb99499SAndroid Build Coastguard Worker ProfilerManager* profiler_manager) {
130*dbb99499SAndroid Build Coastguard Worker internal::ThreadTimer timer(
131*dbb99499SAndroid Build Coastguard Worker b->measure_process_cpu_time()
132*dbb99499SAndroid Build Coastguard Worker ? internal::ThreadTimer::CreateProcessCpuTime()
133*dbb99499SAndroid Build Coastguard Worker : internal::ThreadTimer::Create());
134*dbb99499SAndroid Build Coastguard Worker
135*dbb99499SAndroid Build Coastguard Worker State st = b->Run(iters, thread_id, &timer, manager,
136*dbb99499SAndroid Build Coastguard Worker perf_counters_measurement, profiler_manager);
137*dbb99499SAndroid Build Coastguard Worker BM_CHECK(st.skipped() || st.iterations() >= st.max_iterations)
138*dbb99499SAndroid Build Coastguard Worker << "Benchmark returned before State::KeepRunning() returned false!";
139*dbb99499SAndroid Build Coastguard Worker {
140*dbb99499SAndroid Build Coastguard Worker MutexLock l(manager->GetBenchmarkMutex());
141*dbb99499SAndroid Build Coastguard Worker internal::ThreadManager::Result& results = manager->results;
142*dbb99499SAndroid Build Coastguard Worker results.iterations += st.iterations();
143*dbb99499SAndroid Build Coastguard Worker results.cpu_time_used += timer.cpu_time_used();
144*dbb99499SAndroid Build Coastguard Worker results.real_time_used += timer.real_time_used();
145*dbb99499SAndroid Build Coastguard Worker results.manual_time_used += timer.manual_time_used();
146*dbb99499SAndroid Build Coastguard Worker results.complexity_n += st.complexity_length_n();
147*dbb99499SAndroid Build Coastguard Worker internal::Increment(&results.counters, st.counters);
148*dbb99499SAndroid Build Coastguard Worker }
149*dbb99499SAndroid Build Coastguard Worker manager->NotifyThreadComplete();
150*dbb99499SAndroid Build Coastguard Worker }
151*dbb99499SAndroid Build Coastguard Worker
ComputeMinTime(const benchmark::internal::BenchmarkInstance & b,const BenchTimeType & iters_or_time)152*dbb99499SAndroid Build Coastguard Worker double ComputeMinTime(const benchmark::internal::BenchmarkInstance& b,
153*dbb99499SAndroid Build Coastguard Worker const BenchTimeType& iters_or_time) {
154*dbb99499SAndroid Build Coastguard Worker if (!IsZero(b.min_time())) return b.min_time();
155*dbb99499SAndroid Build Coastguard Worker // If the flag was used to specify number of iters, then return the default
156*dbb99499SAndroid Build Coastguard Worker // min_time.
157*dbb99499SAndroid Build Coastguard Worker if (iters_or_time.tag == BenchTimeType::ITERS) return kDefaultMinTime;
158*dbb99499SAndroid Build Coastguard Worker
159*dbb99499SAndroid Build Coastguard Worker return iters_or_time.time;
160*dbb99499SAndroid Build Coastguard Worker }
161*dbb99499SAndroid Build Coastguard Worker
ComputeIters(const benchmark::internal::BenchmarkInstance & b,const BenchTimeType & iters_or_time)162*dbb99499SAndroid Build Coastguard Worker IterationCount ComputeIters(const benchmark::internal::BenchmarkInstance& b,
163*dbb99499SAndroid Build Coastguard Worker const BenchTimeType& iters_or_time) {
164*dbb99499SAndroid Build Coastguard Worker if (b.iterations() != 0) return b.iterations();
165*dbb99499SAndroid Build Coastguard Worker
166*dbb99499SAndroid Build Coastguard Worker // We've already concluded that this flag is currently used to pass
167*dbb99499SAndroid Build Coastguard Worker // iters but do a check here again anyway.
168*dbb99499SAndroid Build Coastguard Worker BM_CHECK(iters_or_time.tag == BenchTimeType::ITERS);
169*dbb99499SAndroid Build Coastguard Worker return iters_or_time.iters;
170*dbb99499SAndroid Build Coastguard Worker }
171*dbb99499SAndroid Build Coastguard Worker
172*dbb99499SAndroid Build Coastguard Worker } // end namespace
173*dbb99499SAndroid Build Coastguard Worker
ParseBenchMinTime(const std::string & value)174*dbb99499SAndroid Build Coastguard Worker BenchTimeType ParseBenchMinTime(const std::string& value) {
175*dbb99499SAndroid Build Coastguard Worker BenchTimeType ret;
176*dbb99499SAndroid Build Coastguard Worker
177*dbb99499SAndroid Build Coastguard Worker if (value.empty()) {
178*dbb99499SAndroid Build Coastguard Worker ret.tag = BenchTimeType::TIME;
179*dbb99499SAndroid Build Coastguard Worker ret.time = 0.0;
180*dbb99499SAndroid Build Coastguard Worker return ret;
181*dbb99499SAndroid Build Coastguard Worker }
182*dbb99499SAndroid Build Coastguard Worker
183*dbb99499SAndroid Build Coastguard Worker if (value.back() == 'x') {
184*dbb99499SAndroid Build Coastguard Worker char* p_end;
185*dbb99499SAndroid Build Coastguard Worker // Reset errno before it's changed by strtol.
186*dbb99499SAndroid Build Coastguard Worker errno = 0;
187*dbb99499SAndroid Build Coastguard Worker IterationCount num_iters = std::strtol(value.c_str(), &p_end, 10);
188*dbb99499SAndroid Build Coastguard Worker
189*dbb99499SAndroid Build Coastguard Worker // After a valid parse, p_end should have been set to
190*dbb99499SAndroid Build Coastguard Worker // point to the 'x' suffix.
191*dbb99499SAndroid Build Coastguard Worker BM_CHECK(errno == 0 && p_end != nullptr && *p_end == 'x')
192*dbb99499SAndroid Build Coastguard Worker << "Malformed iters value passed to --benchmark_min_time: `" << value
193*dbb99499SAndroid Build Coastguard Worker << "`. Expected --benchmark_min_time=<integer>x.";
194*dbb99499SAndroid Build Coastguard Worker
195*dbb99499SAndroid Build Coastguard Worker ret.tag = BenchTimeType::ITERS;
196*dbb99499SAndroid Build Coastguard Worker ret.iters = num_iters;
197*dbb99499SAndroid Build Coastguard Worker return ret;
198*dbb99499SAndroid Build Coastguard Worker }
199*dbb99499SAndroid Build Coastguard Worker
200*dbb99499SAndroid Build Coastguard Worker bool has_suffix = value.back() == 's';
201*dbb99499SAndroid Build Coastguard Worker if (!has_suffix) {
202*dbb99499SAndroid Build Coastguard Worker BM_VLOG(0) << "Value passed to --benchmark_min_time should have a suffix. "
203*dbb99499SAndroid Build Coastguard Worker "Eg., `30s` for 30-seconds.";
204*dbb99499SAndroid Build Coastguard Worker }
205*dbb99499SAndroid Build Coastguard Worker
206*dbb99499SAndroid Build Coastguard Worker char* p_end;
207*dbb99499SAndroid Build Coastguard Worker // Reset errno before it's changed by strtod.
208*dbb99499SAndroid Build Coastguard Worker errno = 0;
209*dbb99499SAndroid Build Coastguard Worker double min_time = std::strtod(value.c_str(), &p_end);
210*dbb99499SAndroid Build Coastguard Worker
211*dbb99499SAndroid Build Coastguard Worker // After a successful parse, p_end should point to the suffix 's',
212*dbb99499SAndroid Build Coastguard Worker // or the end of the string if the suffix was omitted.
213*dbb99499SAndroid Build Coastguard Worker BM_CHECK(errno == 0 && p_end != nullptr &&
214*dbb99499SAndroid Build Coastguard Worker ((has_suffix && *p_end == 's') || *p_end == '\0'))
215*dbb99499SAndroid Build Coastguard Worker << "Malformed seconds value passed to --benchmark_min_time: `" << value
216*dbb99499SAndroid Build Coastguard Worker << "`. Expected --benchmark_min_time=<float>x.";
217*dbb99499SAndroid Build Coastguard Worker
218*dbb99499SAndroid Build Coastguard Worker ret.tag = BenchTimeType::TIME;
219*dbb99499SAndroid Build Coastguard Worker ret.time = min_time;
220*dbb99499SAndroid Build Coastguard Worker
221*dbb99499SAndroid Build Coastguard Worker return ret;
222*dbb99499SAndroid Build Coastguard Worker }
223*dbb99499SAndroid Build Coastguard Worker
BenchmarkRunner(const benchmark::internal::BenchmarkInstance & b_,PerfCountersMeasurement * pcm_,BenchmarkReporter::PerFamilyRunReports * reports_for_family_)224*dbb99499SAndroid Build Coastguard Worker BenchmarkRunner::BenchmarkRunner(
225*dbb99499SAndroid Build Coastguard Worker const benchmark::internal::BenchmarkInstance& b_,
226*dbb99499SAndroid Build Coastguard Worker PerfCountersMeasurement* pcm_,
227*dbb99499SAndroid Build Coastguard Worker BenchmarkReporter::PerFamilyRunReports* reports_for_family_)
228*dbb99499SAndroid Build Coastguard Worker : b(b_),
229*dbb99499SAndroid Build Coastguard Worker reports_for_family(reports_for_family_),
230*dbb99499SAndroid Build Coastguard Worker parsed_benchtime_flag(ParseBenchMinTime(FLAGS_benchmark_min_time)),
231*dbb99499SAndroid Build Coastguard Worker min_time(ComputeMinTime(b_, parsed_benchtime_flag)),
232*dbb99499SAndroid Build Coastguard Worker min_warmup_time((!IsZero(b.min_time()) && b.min_warmup_time() > 0.0)
233*dbb99499SAndroid Build Coastguard Worker ? b.min_warmup_time()
234*dbb99499SAndroid Build Coastguard Worker : FLAGS_benchmark_min_warmup_time),
235*dbb99499SAndroid Build Coastguard Worker warmup_done(!(min_warmup_time > 0.0)),
236*dbb99499SAndroid Build Coastguard Worker repeats(b.repetitions() != 0 ? b.repetitions()
237*dbb99499SAndroid Build Coastguard Worker : FLAGS_benchmark_repetitions),
238*dbb99499SAndroid Build Coastguard Worker has_explicit_iteration_count(b.iterations() != 0 ||
239*dbb99499SAndroid Build Coastguard Worker parsed_benchtime_flag.tag ==
240*dbb99499SAndroid Build Coastguard Worker BenchTimeType::ITERS),
241*dbb99499SAndroid Build Coastguard Worker pool(static_cast<size_t>(b.threads() - 1)),
242*dbb99499SAndroid Build Coastguard Worker iters(has_explicit_iteration_count
243*dbb99499SAndroid Build Coastguard Worker ? ComputeIters(b_, parsed_benchtime_flag)
244*dbb99499SAndroid Build Coastguard Worker : 1),
245*dbb99499SAndroid Build Coastguard Worker perf_counters_measurement_ptr(pcm_) {
246*dbb99499SAndroid Build Coastguard Worker run_results.display_report_aggregates_only =
247*dbb99499SAndroid Build Coastguard Worker (FLAGS_benchmark_report_aggregates_only ||
248*dbb99499SAndroid Build Coastguard Worker FLAGS_benchmark_display_aggregates_only);
249*dbb99499SAndroid Build Coastguard Worker run_results.file_report_aggregates_only =
250*dbb99499SAndroid Build Coastguard Worker FLAGS_benchmark_report_aggregates_only;
251*dbb99499SAndroid Build Coastguard Worker if (b.aggregation_report_mode() != internal::ARM_Unspecified) {
252*dbb99499SAndroid Build Coastguard Worker run_results.display_report_aggregates_only =
253*dbb99499SAndroid Build Coastguard Worker (b.aggregation_report_mode() &
254*dbb99499SAndroid Build Coastguard Worker internal::ARM_DisplayReportAggregatesOnly);
255*dbb99499SAndroid Build Coastguard Worker run_results.file_report_aggregates_only =
256*dbb99499SAndroid Build Coastguard Worker (b.aggregation_report_mode() & internal::ARM_FileReportAggregatesOnly);
257*dbb99499SAndroid Build Coastguard Worker BM_CHECK(FLAGS_benchmark_perf_counters.empty() ||
258*dbb99499SAndroid Build Coastguard Worker (perf_counters_measurement_ptr->num_counters() == 0))
259*dbb99499SAndroid Build Coastguard Worker << "Perf counters were requested but could not be set up.";
260*dbb99499SAndroid Build Coastguard Worker }
261*dbb99499SAndroid Build Coastguard Worker }
262*dbb99499SAndroid Build Coastguard Worker
DoNIterations()263*dbb99499SAndroid Build Coastguard Worker BenchmarkRunner::IterationResults BenchmarkRunner::DoNIterations() {
264*dbb99499SAndroid Build Coastguard Worker BM_VLOG(2) << "Running " << b.name().str() << " for " << iters << "\n";
265*dbb99499SAndroid Build Coastguard Worker
266*dbb99499SAndroid Build Coastguard Worker std::unique_ptr<internal::ThreadManager> manager;
267*dbb99499SAndroid Build Coastguard Worker manager.reset(new internal::ThreadManager(b.threads()));
268*dbb99499SAndroid Build Coastguard Worker
269*dbb99499SAndroid Build Coastguard Worker // Run all but one thread in separate threads
270*dbb99499SAndroid Build Coastguard Worker for (std::size_t ti = 0; ti < pool.size(); ++ti) {
271*dbb99499SAndroid Build Coastguard Worker pool[ti] = std::thread(&RunInThread, &b, iters, static_cast<int>(ti + 1),
272*dbb99499SAndroid Build Coastguard Worker manager.get(), perf_counters_measurement_ptr,
273*dbb99499SAndroid Build Coastguard Worker /*profiler_manager=*/nullptr);
274*dbb99499SAndroid Build Coastguard Worker }
275*dbb99499SAndroid Build Coastguard Worker // And run one thread here directly.
276*dbb99499SAndroid Build Coastguard Worker // (If we were asked to run just one thread, we don't create new threads.)
277*dbb99499SAndroid Build Coastguard Worker // Yes, we need to do this here *after* we start the separate threads.
278*dbb99499SAndroid Build Coastguard Worker RunInThread(&b, iters, 0, manager.get(), perf_counters_measurement_ptr,
279*dbb99499SAndroid Build Coastguard Worker /*profiler_manager=*/nullptr);
280*dbb99499SAndroid Build Coastguard Worker
281*dbb99499SAndroid Build Coastguard Worker // The main thread has finished. Now let's wait for the other threads.
282*dbb99499SAndroid Build Coastguard Worker manager->WaitForAllThreads();
283*dbb99499SAndroid Build Coastguard Worker for (std::thread& thread : pool) thread.join();
284*dbb99499SAndroid Build Coastguard Worker
285*dbb99499SAndroid Build Coastguard Worker IterationResults i;
286*dbb99499SAndroid Build Coastguard Worker // Acquire the measurements/counters from the manager, UNDER THE LOCK!
287*dbb99499SAndroid Build Coastguard Worker {
288*dbb99499SAndroid Build Coastguard Worker MutexLock l(manager->GetBenchmarkMutex());
289*dbb99499SAndroid Build Coastguard Worker i.results = manager->results;
290*dbb99499SAndroid Build Coastguard Worker }
291*dbb99499SAndroid Build Coastguard Worker
292*dbb99499SAndroid Build Coastguard Worker // And get rid of the manager.
293*dbb99499SAndroid Build Coastguard Worker manager.reset();
294*dbb99499SAndroid Build Coastguard Worker
295*dbb99499SAndroid Build Coastguard Worker BM_VLOG(2) << "Ran in " << i.results.cpu_time_used << "/"
296*dbb99499SAndroid Build Coastguard Worker << i.results.real_time_used << "\n";
297*dbb99499SAndroid Build Coastguard Worker
298*dbb99499SAndroid Build Coastguard Worker // By using KeepRunningBatch a benchmark can iterate more times than
299*dbb99499SAndroid Build Coastguard Worker // requested, so take the iteration count from i.results.
300*dbb99499SAndroid Build Coastguard Worker i.iters = i.results.iterations / b.threads();
301*dbb99499SAndroid Build Coastguard Worker
302*dbb99499SAndroid Build Coastguard Worker // Base decisions off of real time if requested by this benchmark.
303*dbb99499SAndroid Build Coastguard Worker i.seconds = i.results.cpu_time_used;
304*dbb99499SAndroid Build Coastguard Worker if (b.use_manual_time()) {
305*dbb99499SAndroid Build Coastguard Worker i.seconds = i.results.manual_time_used;
306*dbb99499SAndroid Build Coastguard Worker } else if (b.use_real_time()) {
307*dbb99499SAndroid Build Coastguard Worker i.seconds = i.results.real_time_used;
308*dbb99499SAndroid Build Coastguard Worker }
309*dbb99499SAndroid Build Coastguard Worker
310*dbb99499SAndroid Build Coastguard Worker return i;
311*dbb99499SAndroid Build Coastguard Worker }
312*dbb99499SAndroid Build Coastguard Worker
PredictNumItersNeeded(const IterationResults & i) const313*dbb99499SAndroid Build Coastguard Worker IterationCount BenchmarkRunner::PredictNumItersNeeded(
314*dbb99499SAndroid Build Coastguard Worker const IterationResults& i) const {
315*dbb99499SAndroid Build Coastguard Worker // See how much iterations should be increased by.
316*dbb99499SAndroid Build Coastguard Worker // Note: Avoid division by zero with max(seconds, 1ns).
317*dbb99499SAndroid Build Coastguard Worker double multiplier = GetMinTimeToApply() * 1.4 / std::max(i.seconds, 1e-9);
318*dbb99499SAndroid Build Coastguard Worker // If our last run was at least 10% of FLAGS_benchmark_min_time then we
319*dbb99499SAndroid Build Coastguard Worker // use the multiplier directly.
320*dbb99499SAndroid Build Coastguard Worker // Otherwise we use at most 10 times expansion.
321*dbb99499SAndroid Build Coastguard Worker // NOTE: When the last run was at least 10% of the min time the max
322*dbb99499SAndroid Build Coastguard Worker // expansion should be 14x.
323*dbb99499SAndroid Build Coastguard Worker const bool is_significant = (i.seconds / GetMinTimeToApply()) > 0.1;
324*dbb99499SAndroid Build Coastguard Worker multiplier = is_significant ? multiplier : 10.0;
325*dbb99499SAndroid Build Coastguard Worker
326*dbb99499SAndroid Build Coastguard Worker // So what seems to be the sufficiently-large iteration count? Round up.
327*dbb99499SAndroid Build Coastguard Worker const IterationCount max_next_iters = static_cast<IterationCount>(
328*dbb99499SAndroid Build Coastguard Worker std::llround(std::max(multiplier * static_cast<double>(i.iters),
329*dbb99499SAndroid Build Coastguard Worker static_cast<double>(i.iters) + 1.0)));
330*dbb99499SAndroid Build Coastguard Worker // But we do have *some* limits though..
331*dbb99499SAndroid Build Coastguard Worker const IterationCount next_iters = std::min(max_next_iters, kMaxIterations);
332*dbb99499SAndroid Build Coastguard Worker
333*dbb99499SAndroid Build Coastguard Worker BM_VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n";
334*dbb99499SAndroid Build Coastguard Worker return next_iters; // round up before conversion to integer.
335*dbb99499SAndroid Build Coastguard Worker }
336*dbb99499SAndroid Build Coastguard Worker
ShouldReportIterationResults(const IterationResults & i) const337*dbb99499SAndroid Build Coastguard Worker bool BenchmarkRunner::ShouldReportIterationResults(
338*dbb99499SAndroid Build Coastguard Worker const IterationResults& i) const {
339*dbb99499SAndroid Build Coastguard Worker // Determine if this run should be reported;
340*dbb99499SAndroid Build Coastguard Worker // Either it has run for a sufficient amount of time
341*dbb99499SAndroid Build Coastguard Worker // or because an error was reported.
342*dbb99499SAndroid Build Coastguard Worker return i.results.skipped_ ||
343*dbb99499SAndroid Build Coastguard Worker i.iters >= kMaxIterations || // Too many iterations already.
344*dbb99499SAndroid Build Coastguard Worker i.seconds >=
345*dbb99499SAndroid Build Coastguard Worker GetMinTimeToApply() || // The elapsed time is large enough.
346*dbb99499SAndroid Build Coastguard Worker // CPU time is specified but the elapsed real time greatly exceeds
347*dbb99499SAndroid Build Coastguard Worker // the minimum time.
348*dbb99499SAndroid Build Coastguard Worker // Note that user provided timers are except from this test.
349*dbb99499SAndroid Build Coastguard Worker ((i.results.real_time_used >= 5 * GetMinTimeToApply()) &&
350*dbb99499SAndroid Build Coastguard Worker !b.use_manual_time());
351*dbb99499SAndroid Build Coastguard Worker }
352*dbb99499SAndroid Build Coastguard Worker
GetMinTimeToApply() const353*dbb99499SAndroid Build Coastguard Worker double BenchmarkRunner::GetMinTimeToApply() const {
354*dbb99499SAndroid Build Coastguard Worker // In order to re-use functionality to run and measure benchmarks for running
355*dbb99499SAndroid Build Coastguard Worker // a warmup phase of the benchmark, we need a way of telling whether to apply
356*dbb99499SAndroid Build Coastguard Worker // min_time or min_warmup_time. This function will figure out if we are in the
357*dbb99499SAndroid Build Coastguard Worker // warmup phase and therefore need to apply min_warmup_time or if we already
358*dbb99499SAndroid Build Coastguard Worker // in the benchmarking phase and min_time needs to be applied.
359*dbb99499SAndroid Build Coastguard Worker return warmup_done ? min_time : min_warmup_time;
360*dbb99499SAndroid Build Coastguard Worker }
361*dbb99499SAndroid Build Coastguard Worker
FinishWarmUp(const IterationCount & i)362*dbb99499SAndroid Build Coastguard Worker void BenchmarkRunner::FinishWarmUp(const IterationCount& i) {
363*dbb99499SAndroid Build Coastguard Worker warmup_done = true;
364*dbb99499SAndroid Build Coastguard Worker iters = i;
365*dbb99499SAndroid Build Coastguard Worker }
366*dbb99499SAndroid Build Coastguard Worker
RunWarmUp()367*dbb99499SAndroid Build Coastguard Worker void BenchmarkRunner::RunWarmUp() {
368*dbb99499SAndroid Build Coastguard Worker // Use the same mechanisms for warming up the benchmark as used for actually
369*dbb99499SAndroid Build Coastguard Worker // running and measuring the benchmark.
370*dbb99499SAndroid Build Coastguard Worker IterationResults i_warmup;
371*dbb99499SAndroid Build Coastguard Worker // Dont use the iterations determined in the warmup phase for the actual
372*dbb99499SAndroid Build Coastguard Worker // measured benchmark phase. While this may be a good starting point for the
373*dbb99499SAndroid Build Coastguard Worker // benchmark and it would therefore get rid of the need to figure out how many
374*dbb99499SAndroid Build Coastguard Worker // iterations are needed if min_time is set again, this may also be a complete
375*dbb99499SAndroid Build Coastguard Worker // wrong guess since the warmup loops might be considerably slower (e.g
376*dbb99499SAndroid Build Coastguard Worker // because of caching effects).
377*dbb99499SAndroid Build Coastguard Worker const IterationCount i_backup = iters;
378*dbb99499SAndroid Build Coastguard Worker
379*dbb99499SAndroid Build Coastguard Worker for (;;) {
380*dbb99499SAndroid Build Coastguard Worker b.Setup();
381*dbb99499SAndroid Build Coastguard Worker i_warmup = DoNIterations();
382*dbb99499SAndroid Build Coastguard Worker b.Teardown();
383*dbb99499SAndroid Build Coastguard Worker
384*dbb99499SAndroid Build Coastguard Worker const bool finish = ShouldReportIterationResults(i_warmup);
385*dbb99499SAndroid Build Coastguard Worker
386*dbb99499SAndroid Build Coastguard Worker if (finish) {
387*dbb99499SAndroid Build Coastguard Worker FinishWarmUp(i_backup);
388*dbb99499SAndroid Build Coastguard Worker break;
389*dbb99499SAndroid Build Coastguard Worker }
390*dbb99499SAndroid Build Coastguard Worker
391*dbb99499SAndroid Build Coastguard Worker // Although we are running "only" a warmup phase where running enough
392*dbb99499SAndroid Build Coastguard Worker // iterations at once without measuring time isn't as important as it is for
393*dbb99499SAndroid Build Coastguard Worker // the benchmarking phase, we still do it the same way as otherwise it is
394*dbb99499SAndroid Build Coastguard Worker // very confusing for the user to know how to choose a proper value for
395*dbb99499SAndroid Build Coastguard Worker // min_warmup_time if a different approach on running it is used.
396*dbb99499SAndroid Build Coastguard Worker iters = PredictNumItersNeeded(i_warmup);
397*dbb99499SAndroid Build Coastguard Worker assert(iters > i_warmup.iters &&
398*dbb99499SAndroid Build Coastguard Worker "if we did more iterations than we want to do the next time, "
399*dbb99499SAndroid Build Coastguard Worker "then we should have accepted the current iteration run.");
400*dbb99499SAndroid Build Coastguard Worker }
401*dbb99499SAndroid Build Coastguard Worker }
402*dbb99499SAndroid Build Coastguard Worker
RunMemoryManager(IterationCount memory_iterations)403*dbb99499SAndroid Build Coastguard Worker MemoryManager::Result* BenchmarkRunner::RunMemoryManager(
404*dbb99499SAndroid Build Coastguard Worker IterationCount memory_iterations) {
405*dbb99499SAndroid Build Coastguard Worker // TODO(vyng): Consider making BenchmarkReporter::Run::memory_result an
406*dbb99499SAndroid Build Coastguard Worker // optional so we don't have to own the Result here.
407*dbb99499SAndroid Build Coastguard Worker // Can't do it now due to cxx03.
408*dbb99499SAndroid Build Coastguard Worker memory_results.push_back(MemoryManager::Result());
409*dbb99499SAndroid Build Coastguard Worker MemoryManager::Result* memory_result = &memory_results.back();
410*dbb99499SAndroid Build Coastguard Worker memory_manager->Start();
411*dbb99499SAndroid Build Coastguard Worker std::unique_ptr<internal::ThreadManager> manager;
412*dbb99499SAndroid Build Coastguard Worker manager.reset(new internal::ThreadManager(1));
413*dbb99499SAndroid Build Coastguard Worker b.Setup();
414*dbb99499SAndroid Build Coastguard Worker RunInThread(&b, memory_iterations, 0, manager.get(),
415*dbb99499SAndroid Build Coastguard Worker perf_counters_measurement_ptr,
416*dbb99499SAndroid Build Coastguard Worker /*profiler_manager=*/nullptr);
417*dbb99499SAndroid Build Coastguard Worker manager->WaitForAllThreads();
418*dbb99499SAndroid Build Coastguard Worker manager.reset();
419*dbb99499SAndroid Build Coastguard Worker b.Teardown();
420*dbb99499SAndroid Build Coastguard Worker memory_manager->Stop(*memory_result);
421*dbb99499SAndroid Build Coastguard Worker return memory_result;
422*dbb99499SAndroid Build Coastguard Worker }
423*dbb99499SAndroid Build Coastguard Worker
RunProfilerManager()424*dbb99499SAndroid Build Coastguard Worker void BenchmarkRunner::RunProfilerManager() {
425*dbb99499SAndroid Build Coastguard Worker // TODO: Provide a way to specify the number of iterations.
426*dbb99499SAndroid Build Coastguard Worker IterationCount profile_iterations = 1;
427*dbb99499SAndroid Build Coastguard Worker std::unique_ptr<internal::ThreadManager> manager;
428*dbb99499SAndroid Build Coastguard Worker manager.reset(new internal::ThreadManager(1));
429*dbb99499SAndroid Build Coastguard Worker b.Setup();
430*dbb99499SAndroid Build Coastguard Worker RunInThread(&b, profile_iterations, 0, manager.get(),
431*dbb99499SAndroid Build Coastguard Worker /*perf_counters_measurement_ptr=*/nullptr,
432*dbb99499SAndroid Build Coastguard Worker /*profiler_manager=*/profiler_manager);
433*dbb99499SAndroid Build Coastguard Worker manager->WaitForAllThreads();
434*dbb99499SAndroid Build Coastguard Worker manager.reset();
435*dbb99499SAndroid Build Coastguard Worker b.Teardown();
436*dbb99499SAndroid Build Coastguard Worker }
437*dbb99499SAndroid Build Coastguard Worker
DoOneRepetition()438*dbb99499SAndroid Build Coastguard Worker void BenchmarkRunner::DoOneRepetition() {
439*dbb99499SAndroid Build Coastguard Worker assert(HasRepeatsRemaining() && "Already done all repetitions?");
440*dbb99499SAndroid Build Coastguard Worker
441*dbb99499SAndroid Build Coastguard Worker const bool is_the_first_repetition = num_repetitions_done == 0;
442*dbb99499SAndroid Build Coastguard Worker
443*dbb99499SAndroid Build Coastguard Worker // In case a warmup phase is requested by the benchmark, run it now.
444*dbb99499SAndroid Build Coastguard Worker // After running the warmup phase the BenchmarkRunner should be in a state as
445*dbb99499SAndroid Build Coastguard Worker // this warmup never happened except the fact that warmup_done is set. Every
446*dbb99499SAndroid Build Coastguard Worker // other manipulation of the BenchmarkRunner instance would be a bug! Please
447*dbb99499SAndroid Build Coastguard Worker // fix it.
448*dbb99499SAndroid Build Coastguard Worker if (!warmup_done) RunWarmUp();
449*dbb99499SAndroid Build Coastguard Worker
450*dbb99499SAndroid Build Coastguard Worker IterationResults i;
451*dbb99499SAndroid Build Coastguard Worker // We *may* be gradually increasing the length (iteration count)
452*dbb99499SAndroid Build Coastguard Worker // of the benchmark until we decide the results are significant.
453*dbb99499SAndroid Build Coastguard Worker // And once we do, we report those last results and exit.
454*dbb99499SAndroid Build Coastguard Worker // Please do note that the if there are repetitions, the iteration count
455*dbb99499SAndroid Build Coastguard Worker // is *only* calculated for the *first* repetition, and other repetitions
456*dbb99499SAndroid Build Coastguard Worker // simply use that precomputed iteration count.
457*dbb99499SAndroid Build Coastguard Worker for (;;) {
458*dbb99499SAndroid Build Coastguard Worker b.Setup();
459*dbb99499SAndroid Build Coastguard Worker i = DoNIterations();
460*dbb99499SAndroid Build Coastguard Worker b.Teardown();
461*dbb99499SAndroid Build Coastguard Worker
462*dbb99499SAndroid Build Coastguard Worker // Do we consider the results to be significant?
463*dbb99499SAndroid Build Coastguard Worker // If we are doing repetitions, and the first repetition was already done,
464*dbb99499SAndroid Build Coastguard Worker // it has calculated the correct iteration time, so we have run that very
465*dbb99499SAndroid Build Coastguard Worker // iteration count just now. No need to calculate anything. Just report.
466*dbb99499SAndroid Build Coastguard Worker // Else, the normal rules apply.
467*dbb99499SAndroid Build Coastguard Worker const bool results_are_significant = !is_the_first_repetition ||
468*dbb99499SAndroid Build Coastguard Worker has_explicit_iteration_count ||
469*dbb99499SAndroid Build Coastguard Worker ShouldReportIterationResults(i);
470*dbb99499SAndroid Build Coastguard Worker
471*dbb99499SAndroid Build Coastguard Worker if (results_are_significant) break; // Good, let's report them!
472*dbb99499SAndroid Build Coastguard Worker
473*dbb99499SAndroid Build Coastguard Worker // Nope, bad iteration. Let's re-estimate the hopefully-sufficient
474*dbb99499SAndroid Build Coastguard Worker // iteration count, and run the benchmark again...
475*dbb99499SAndroid Build Coastguard Worker
476*dbb99499SAndroid Build Coastguard Worker iters = PredictNumItersNeeded(i);
477*dbb99499SAndroid Build Coastguard Worker assert(iters > i.iters &&
478*dbb99499SAndroid Build Coastguard Worker "if we did more iterations than we want to do the next time, "
479*dbb99499SAndroid Build Coastguard Worker "then we should have accepted the current iteration run.");
480*dbb99499SAndroid Build Coastguard Worker }
481*dbb99499SAndroid Build Coastguard Worker
482*dbb99499SAndroid Build Coastguard Worker // Produce memory measurements if requested.
483*dbb99499SAndroid Build Coastguard Worker MemoryManager::Result* memory_result = nullptr;
484*dbb99499SAndroid Build Coastguard Worker IterationCount memory_iterations = 0;
485*dbb99499SAndroid Build Coastguard Worker if (memory_manager != nullptr) {
486*dbb99499SAndroid Build Coastguard Worker // Only run a few iterations to reduce the impact of one-time
487*dbb99499SAndroid Build Coastguard Worker // allocations in benchmarks that are not properly managed.
488*dbb99499SAndroid Build Coastguard Worker memory_iterations = std::min<IterationCount>(16, iters);
489*dbb99499SAndroid Build Coastguard Worker memory_result = RunMemoryManager(memory_iterations);
490*dbb99499SAndroid Build Coastguard Worker }
491*dbb99499SAndroid Build Coastguard Worker
492*dbb99499SAndroid Build Coastguard Worker if (profiler_manager != nullptr) {
493*dbb99499SAndroid Build Coastguard Worker RunProfilerManager();
494*dbb99499SAndroid Build Coastguard Worker }
495*dbb99499SAndroid Build Coastguard Worker
496*dbb99499SAndroid Build Coastguard Worker // Ok, now actually report.
497*dbb99499SAndroid Build Coastguard Worker BenchmarkReporter::Run report =
498*dbb99499SAndroid Build Coastguard Worker CreateRunReport(b, i.results, memory_iterations, memory_result, i.seconds,
499*dbb99499SAndroid Build Coastguard Worker num_repetitions_done, repeats);
500*dbb99499SAndroid Build Coastguard Worker
501*dbb99499SAndroid Build Coastguard Worker if (reports_for_family) {
502*dbb99499SAndroid Build Coastguard Worker ++reports_for_family->num_runs_done;
503*dbb99499SAndroid Build Coastguard Worker if (!report.skipped) reports_for_family->Runs.push_back(report);
504*dbb99499SAndroid Build Coastguard Worker }
505*dbb99499SAndroid Build Coastguard Worker
506*dbb99499SAndroid Build Coastguard Worker run_results.non_aggregates.push_back(report);
507*dbb99499SAndroid Build Coastguard Worker
508*dbb99499SAndroid Build Coastguard Worker ++num_repetitions_done;
509*dbb99499SAndroid Build Coastguard Worker }
510*dbb99499SAndroid Build Coastguard Worker
GetResults()511*dbb99499SAndroid Build Coastguard Worker RunResults&& BenchmarkRunner::GetResults() {
512*dbb99499SAndroid Build Coastguard Worker assert(!HasRepeatsRemaining() && "Did not run all repetitions yet?");
513*dbb99499SAndroid Build Coastguard Worker
514*dbb99499SAndroid Build Coastguard Worker // Calculate additional statistics over the repetitions of this instance.
515*dbb99499SAndroid Build Coastguard Worker run_results.aggregates_only = ComputeStats(run_results.non_aggregates);
516*dbb99499SAndroid Build Coastguard Worker
517*dbb99499SAndroid Build Coastguard Worker return std::move(run_results);
518*dbb99499SAndroid Build Coastguard Worker }
519*dbb99499SAndroid Build Coastguard Worker
520*dbb99499SAndroid Build Coastguard Worker } // end namespace internal
521*dbb99499SAndroid Build Coastguard Worker
522*dbb99499SAndroid Build Coastguard Worker } // end namespace benchmark
523