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_runner.h"
16*58b9f456SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
17*58b9f456SAndroid Build Coastguard Worker #include "benchmark_api_internal.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 namespace benchmark {
55*58b9f456SAndroid Build Coastguard Worker
56*58b9f456SAndroid Build Coastguard Worker namespace internal {
57*58b9f456SAndroid Build Coastguard Worker
58*58b9f456SAndroid Build Coastguard Worker MemoryManager* memory_manager = nullptr;
59*58b9f456SAndroid Build Coastguard Worker
60*58b9f456SAndroid Build Coastguard Worker namespace {
61*58b9f456SAndroid Build Coastguard Worker
62*58b9f456SAndroid Build Coastguard Worker static const size_t kMaxIterations = 1000000000;
63*58b9f456SAndroid Build Coastguard Worker
CreateRunReport(const benchmark::internal::BenchmarkInstance & b,const internal::ThreadManager::Result & results,size_t memory_iterations,const MemoryManager::Result & memory_result,double seconds)64*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter::Run CreateRunReport(
65*58b9f456SAndroid Build Coastguard Worker const benchmark::internal::BenchmarkInstance& b,
66*58b9f456SAndroid Build Coastguard Worker const internal::ThreadManager::Result& results, size_t memory_iterations,
67*58b9f456SAndroid Build Coastguard Worker const MemoryManager::Result& memory_result, double seconds) {
68*58b9f456SAndroid Build Coastguard Worker // Create report about this benchmark run.
69*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter::Run report;
70*58b9f456SAndroid Build Coastguard Worker
71*58b9f456SAndroid Build Coastguard Worker report.run_name = b.name;
72*58b9f456SAndroid Build Coastguard Worker report.error_occurred = results.has_error_;
73*58b9f456SAndroid Build Coastguard Worker report.error_message = results.error_message_;
74*58b9f456SAndroid Build Coastguard Worker report.report_label = results.report_label_;
75*58b9f456SAndroid Build Coastguard Worker // This is the total iterations across all threads.
76*58b9f456SAndroid Build Coastguard Worker report.iterations = results.iterations;
77*58b9f456SAndroid Build Coastguard Worker report.time_unit = b.time_unit;
78*58b9f456SAndroid Build Coastguard Worker
79*58b9f456SAndroid Build Coastguard Worker if (!report.error_occurred) {
80*58b9f456SAndroid Build Coastguard Worker if (b.use_manual_time) {
81*58b9f456SAndroid Build Coastguard Worker report.real_accumulated_time = results.manual_time_used;
82*58b9f456SAndroid Build Coastguard Worker } else {
83*58b9f456SAndroid Build Coastguard Worker report.real_accumulated_time = results.real_time_used;
84*58b9f456SAndroid Build Coastguard Worker }
85*58b9f456SAndroid Build Coastguard Worker report.cpu_accumulated_time = results.cpu_time_used;
86*58b9f456SAndroid Build Coastguard Worker report.complexity_n = results.complexity_n;
87*58b9f456SAndroid Build Coastguard Worker report.complexity = b.complexity;
88*58b9f456SAndroid Build Coastguard Worker report.complexity_lambda = b.complexity_lambda;
89*58b9f456SAndroid Build Coastguard Worker report.statistics = b.statistics;
90*58b9f456SAndroid Build Coastguard Worker report.counters = results.counters;
91*58b9f456SAndroid Build Coastguard Worker
92*58b9f456SAndroid Build Coastguard Worker if (memory_iterations > 0) {
93*58b9f456SAndroid Build Coastguard Worker report.has_memory_result = true;
94*58b9f456SAndroid Build Coastguard Worker report.allocs_per_iter =
95*58b9f456SAndroid Build Coastguard Worker memory_iterations ? static_cast<double>(memory_result.num_allocs) /
96*58b9f456SAndroid Build Coastguard Worker memory_iterations
97*58b9f456SAndroid Build Coastguard Worker : 0;
98*58b9f456SAndroid Build Coastguard Worker report.max_bytes_used = memory_result.max_bytes_used;
99*58b9f456SAndroid Build Coastguard Worker }
100*58b9f456SAndroid Build Coastguard Worker
101*58b9f456SAndroid Build Coastguard Worker internal::Finish(&report.counters, results.iterations, seconds, b.threads);
102*58b9f456SAndroid Build Coastguard Worker }
103*58b9f456SAndroid Build Coastguard Worker return report;
104*58b9f456SAndroid Build Coastguard Worker }
105*58b9f456SAndroid Build Coastguard Worker
106*58b9f456SAndroid Build Coastguard Worker // Execute one thread of benchmark b for the specified number of iterations.
107*58b9f456SAndroid Build Coastguard Worker // Adds the stats collected for the thread into *total.
RunInThread(const BenchmarkInstance * b,size_t iters,int thread_id,ThreadManager * manager)108*58b9f456SAndroid Build Coastguard Worker void RunInThread(const BenchmarkInstance* b, size_t iters, int thread_id,
109*58b9f456SAndroid Build Coastguard Worker ThreadManager* manager) {
110*58b9f456SAndroid Build Coastguard Worker internal::ThreadTimer timer;
111*58b9f456SAndroid Build Coastguard Worker State st = b->Run(iters, thread_id, &timer, manager);
112*58b9f456SAndroid Build Coastguard Worker CHECK(st.iterations() >= st.max_iterations)
113*58b9f456SAndroid Build Coastguard Worker << "Benchmark returned before State::KeepRunning() returned false!";
114*58b9f456SAndroid Build Coastguard Worker {
115*58b9f456SAndroid Build Coastguard Worker MutexLock l(manager->GetBenchmarkMutex());
116*58b9f456SAndroid Build Coastguard Worker internal::ThreadManager::Result& results = manager->results;
117*58b9f456SAndroid Build Coastguard Worker results.iterations += st.iterations();
118*58b9f456SAndroid Build Coastguard Worker results.cpu_time_used += timer.cpu_time_used();
119*58b9f456SAndroid Build Coastguard Worker results.real_time_used += timer.real_time_used();
120*58b9f456SAndroid Build Coastguard Worker results.manual_time_used += timer.manual_time_used();
121*58b9f456SAndroid Build Coastguard Worker results.complexity_n += st.complexity_length_n();
122*58b9f456SAndroid Build Coastguard Worker internal::Increment(&results.counters, st.counters);
123*58b9f456SAndroid Build Coastguard Worker }
124*58b9f456SAndroid Build Coastguard Worker manager->NotifyThreadComplete();
125*58b9f456SAndroid Build Coastguard Worker }
126*58b9f456SAndroid Build Coastguard Worker
127*58b9f456SAndroid Build Coastguard Worker class BenchmarkRunner {
128*58b9f456SAndroid Build Coastguard Worker public:
BenchmarkRunner(const benchmark::internal::BenchmarkInstance & b_,std::vector<BenchmarkReporter::Run> * complexity_reports_)129*58b9f456SAndroid Build Coastguard Worker BenchmarkRunner(const benchmark::internal::BenchmarkInstance& b_,
130*58b9f456SAndroid Build Coastguard Worker std::vector<BenchmarkReporter::Run>* complexity_reports_)
131*58b9f456SAndroid Build Coastguard Worker : b(b_),
132*58b9f456SAndroid Build Coastguard Worker complexity_reports(*complexity_reports_),
133*58b9f456SAndroid Build Coastguard Worker min_time(!IsZero(b.min_time) ? b.min_time : FLAGS_benchmark_min_time),
134*58b9f456SAndroid Build Coastguard Worker repeats(b.repetitions != 0 ? b.repetitions
135*58b9f456SAndroid Build Coastguard Worker : FLAGS_benchmark_repetitions),
136*58b9f456SAndroid Build Coastguard Worker has_explicit_iteration_count(b.iterations != 0),
137*58b9f456SAndroid Build Coastguard Worker pool(b.threads - 1),
138*58b9f456SAndroid Build Coastguard Worker iters(has_explicit_iteration_count ? b.iterations : 1) {
139*58b9f456SAndroid Build Coastguard Worker run_results.display_report_aggregates_only =
140*58b9f456SAndroid Build Coastguard Worker (FLAGS_benchmark_report_aggregates_only ||
141*58b9f456SAndroid Build Coastguard Worker FLAGS_benchmark_display_aggregates_only);
142*58b9f456SAndroid Build Coastguard Worker run_results.file_report_aggregates_only =
143*58b9f456SAndroid Build Coastguard Worker FLAGS_benchmark_report_aggregates_only;
144*58b9f456SAndroid Build Coastguard Worker if (b.aggregation_report_mode != internal::ARM_Unspecified) {
145*58b9f456SAndroid Build Coastguard Worker run_results.display_report_aggregates_only =
146*58b9f456SAndroid Build Coastguard Worker (b.aggregation_report_mode &
147*58b9f456SAndroid Build Coastguard Worker internal::ARM_DisplayReportAggregatesOnly);
148*58b9f456SAndroid Build Coastguard Worker run_results.file_report_aggregates_only =
149*58b9f456SAndroid Build Coastguard Worker (b.aggregation_report_mode & internal::ARM_FileReportAggregatesOnly);
150*58b9f456SAndroid Build Coastguard Worker }
151*58b9f456SAndroid Build Coastguard Worker
152*58b9f456SAndroid Build Coastguard Worker for (int repetition_num = 0; repetition_num < repeats; repetition_num++) {
153*58b9f456SAndroid Build Coastguard Worker const bool is_the_first_repetition = repetition_num == 0;
154*58b9f456SAndroid Build Coastguard Worker DoOneRepetition(is_the_first_repetition);
155*58b9f456SAndroid Build Coastguard Worker }
156*58b9f456SAndroid Build Coastguard Worker
157*58b9f456SAndroid Build Coastguard Worker // Calculate additional statistics
158*58b9f456SAndroid Build Coastguard Worker run_results.aggregates_only = ComputeStats(run_results.non_aggregates);
159*58b9f456SAndroid Build Coastguard Worker
160*58b9f456SAndroid Build Coastguard Worker // Maybe calculate complexity report
161*58b9f456SAndroid Build Coastguard Worker if ((b.complexity != oNone) && b.last_benchmark_instance) {
162*58b9f456SAndroid Build Coastguard Worker auto additional_run_stats = ComputeBigO(complexity_reports);
163*58b9f456SAndroid Build Coastguard Worker run_results.aggregates_only.insert(run_results.aggregates_only.end(),
164*58b9f456SAndroid Build Coastguard Worker additional_run_stats.begin(),
165*58b9f456SAndroid Build Coastguard Worker additional_run_stats.end());
166*58b9f456SAndroid Build Coastguard Worker complexity_reports.clear();
167*58b9f456SAndroid Build Coastguard Worker }
168*58b9f456SAndroid Build Coastguard Worker }
169*58b9f456SAndroid Build Coastguard Worker
get_results()170*58b9f456SAndroid Build Coastguard Worker RunResults&& get_results() { return std::move(run_results); }
171*58b9f456SAndroid Build Coastguard Worker
172*58b9f456SAndroid Build Coastguard Worker private:
173*58b9f456SAndroid Build Coastguard Worker RunResults run_results;
174*58b9f456SAndroid Build Coastguard Worker
175*58b9f456SAndroid Build Coastguard Worker const benchmark::internal::BenchmarkInstance& b;
176*58b9f456SAndroid Build Coastguard Worker std::vector<BenchmarkReporter::Run>& complexity_reports;
177*58b9f456SAndroid Build Coastguard Worker
178*58b9f456SAndroid Build Coastguard Worker const double min_time;
179*58b9f456SAndroid Build Coastguard Worker const int repeats;
180*58b9f456SAndroid Build Coastguard Worker const bool has_explicit_iteration_count;
181*58b9f456SAndroid Build Coastguard Worker
182*58b9f456SAndroid Build Coastguard Worker std::vector<std::thread> pool;
183*58b9f456SAndroid Build Coastguard Worker
184*58b9f456SAndroid Build Coastguard Worker size_t iters; // preserved between repetitions!
185*58b9f456SAndroid Build Coastguard Worker // So only the first repetition has to find/calculate it,
186*58b9f456SAndroid Build Coastguard Worker // the other repetitions will just use that precomputed iteration count.
187*58b9f456SAndroid Build Coastguard Worker
188*58b9f456SAndroid Build Coastguard Worker struct IterationResults {
189*58b9f456SAndroid Build Coastguard Worker internal::ThreadManager::Result results;
190*58b9f456SAndroid Build Coastguard Worker size_t iters;
191*58b9f456SAndroid Build Coastguard Worker double seconds;
192*58b9f456SAndroid Build Coastguard Worker };
DoNIterations()193*58b9f456SAndroid Build Coastguard Worker IterationResults DoNIterations() {
194*58b9f456SAndroid Build Coastguard Worker VLOG(2) << "Running " << b.name << " for " << iters << "\n";
195*58b9f456SAndroid Build Coastguard Worker
196*58b9f456SAndroid Build Coastguard Worker std::unique_ptr<internal::ThreadManager> manager;
197*58b9f456SAndroid Build Coastguard Worker manager.reset(new internal::ThreadManager(b.threads));
198*58b9f456SAndroid Build Coastguard Worker
199*58b9f456SAndroid Build Coastguard Worker // Run all but one thread in separate threads
200*58b9f456SAndroid Build Coastguard Worker for (std::size_t ti = 0; ti < pool.size(); ++ti) {
201*58b9f456SAndroid Build Coastguard Worker pool[ti] = std::thread(&RunInThread, &b, iters, static_cast<int>(ti + 1),
202*58b9f456SAndroid Build Coastguard Worker manager.get());
203*58b9f456SAndroid Build Coastguard Worker }
204*58b9f456SAndroid Build Coastguard Worker // And run one thread here directly.
205*58b9f456SAndroid Build Coastguard Worker // (If we were asked to run just one thread, we don't create new threads.)
206*58b9f456SAndroid Build Coastguard Worker // Yes, we need to do this here *after* we start the separate threads.
207*58b9f456SAndroid Build Coastguard Worker RunInThread(&b, iters, 0, manager.get());
208*58b9f456SAndroid Build Coastguard Worker
209*58b9f456SAndroid Build Coastguard Worker // The main thread has finished. Now let's wait for the other threads.
210*58b9f456SAndroid Build Coastguard Worker manager->WaitForAllThreads();
211*58b9f456SAndroid Build Coastguard Worker for (std::thread& thread : pool) thread.join();
212*58b9f456SAndroid Build Coastguard Worker
213*58b9f456SAndroid Build Coastguard Worker IterationResults i;
214*58b9f456SAndroid Build Coastguard Worker // Acquire the measurements/counters from the manager, UNDER THE LOCK!
215*58b9f456SAndroid Build Coastguard Worker {
216*58b9f456SAndroid Build Coastguard Worker MutexLock l(manager->GetBenchmarkMutex());
217*58b9f456SAndroid Build Coastguard Worker i.results = manager->results;
218*58b9f456SAndroid Build Coastguard Worker }
219*58b9f456SAndroid Build Coastguard Worker
220*58b9f456SAndroid Build Coastguard Worker // And get rid of the manager.
221*58b9f456SAndroid Build Coastguard Worker manager.reset();
222*58b9f456SAndroid Build Coastguard Worker
223*58b9f456SAndroid Build Coastguard Worker // Adjust real/manual time stats since they were reported per thread.
224*58b9f456SAndroid Build Coastguard Worker i.results.real_time_used /= b.threads;
225*58b9f456SAndroid Build Coastguard Worker i.results.manual_time_used /= b.threads;
226*58b9f456SAndroid Build Coastguard Worker
227*58b9f456SAndroid Build Coastguard Worker VLOG(2) << "Ran in " << i.results.cpu_time_used << "/"
228*58b9f456SAndroid Build Coastguard Worker << i.results.real_time_used << "\n";
229*58b9f456SAndroid Build Coastguard Worker
230*58b9f456SAndroid Build Coastguard Worker // So for how long were we running?
231*58b9f456SAndroid Build Coastguard Worker i.iters = iters;
232*58b9f456SAndroid Build Coastguard Worker // Base decisions off of real time if requested by this benchmark.
233*58b9f456SAndroid Build Coastguard Worker i.seconds = i.results.cpu_time_used;
234*58b9f456SAndroid Build Coastguard Worker if (b.use_manual_time) {
235*58b9f456SAndroid Build Coastguard Worker i.seconds = i.results.manual_time_used;
236*58b9f456SAndroid Build Coastguard Worker } else if (b.use_real_time) {
237*58b9f456SAndroid Build Coastguard Worker i.seconds = i.results.real_time_used;
238*58b9f456SAndroid Build Coastguard Worker }
239*58b9f456SAndroid Build Coastguard Worker
240*58b9f456SAndroid Build Coastguard Worker return i;
241*58b9f456SAndroid Build Coastguard Worker }
242*58b9f456SAndroid Build Coastguard Worker
PredictNumItersNeeded(const IterationResults & i) const243*58b9f456SAndroid Build Coastguard Worker size_t PredictNumItersNeeded(const IterationResults& i) const {
244*58b9f456SAndroid Build Coastguard Worker // See how much iterations should be increased by.
245*58b9f456SAndroid Build Coastguard Worker // Note: Avoid division by zero with max(seconds, 1ns).
246*58b9f456SAndroid Build Coastguard Worker double multiplier = min_time * 1.4 / std::max(i.seconds, 1e-9);
247*58b9f456SAndroid Build Coastguard Worker // If our last run was at least 10% of FLAGS_benchmark_min_time then we
248*58b9f456SAndroid Build Coastguard Worker // use the multiplier directly.
249*58b9f456SAndroid Build Coastguard Worker // Otherwise we use at most 10 times expansion.
250*58b9f456SAndroid Build Coastguard Worker // NOTE: When the last run was at least 10% of the min time the max
251*58b9f456SAndroid Build Coastguard Worker // expansion should be 14x.
252*58b9f456SAndroid Build Coastguard Worker bool is_significant = (i.seconds / min_time) > 0.1;
253*58b9f456SAndroid Build Coastguard Worker multiplier = is_significant ? multiplier : std::min(10.0, multiplier);
254*58b9f456SAndroid Build Coastguard Worker if (multiplier <= 1.0) multiplier = 2.0;
255*58b9f456SAndroid Build Coastguard Worker
256*58b9f456SAndroid Build Coastguard Worker // So what seems to be the sufficiently-large iteration count? Round up.
257*58b9f456SAndroid Build Coastguard Worker const size_t max_next_iters =
258*58b9f456SAndroid Build Coastguard Worker 0.5 + std::max(multiplier * i.iters, i.iters + 1.0);
259*58b9f456SAndroid Build Coastguard Worker // But we do have *some* sanity limits though..
260*58b9f456SAndroid Build Coastguard Worker const size_t next_iters = std::min(max_next_iters, kMaxIterations);
261*58b9f456SAndroid Build Coastguard Worker
262*58b9f456SAndroid Build Coastguard Worker VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n";
263*58b9f456SAndroid Build Coastguard Worker return next_iters; // round up before conversion to integer.
264*58b9f456SAndroid Build Coastguard Worker }
265*58b9f456SAndroid Build Coastguard Worker
ShouldReportIterationResults(const IterationResults & i) const266*58b9f456SAndroid Build Coastguard Worker bool ShouldReportIterationResults(const IterationResults& i) const {
267*58b9f456SAndroid Build Coastguard Worker // Determine if this run should be reported;
268*58b9f456SAndroid Build Coastguard Worker // Either it has run for a sufficient amount of time
269*58b9f456SAndroid Build Coastguard Worker // or because an error was reported.
270*58b9f456SAndroid Build Coastguard Worker return i.results.has_error_ ||
271*58b9f456SAndroid Build Coastguard Worker i.iters >= kMaxIterations || // Too many iterations already.
272*58b9f456SAndroid Build Coastguard Worker i.seconds >= min_time || // The elapsed time is large enough.
273*58b9f456SAndroid Build Coastguard Worker // CPU time is specified but the elapsed real time greatly exceeds
274*58b9f456SAndroid Build Coastguard Worker // the minimum time.
275*58b9f456SAndroid Build Coastguard Worker // Note that user provided timers are except from this sanity check.
276*58b9f456SAndroid Build Coastguard Worker ((i.results.real_time_used >= 5 * min_time) && !b.use_manual_time);
277*58b9f456SAndroid Build Coastguard Worker }
278*58b9f456SAndroid Build Coastguard Worker
DoOneRepetition(bool is_the_first_repetition)279*58b9f456SAndroid Build Coastguard Worker void DoOneRepetition(bool is_the_first_repetition) {
280*58b9f456SAndroid Build Coastguard Worker IterationResults i;
281*58b9f456SAndroid Build Coastguard Worker
282*58b9f456SAndroid Build Coastguard Worker // We *may* be gradually increasing the length (iteration count)
283*58b9f456SAndroid Build Coastguard Worker // of the benchmark until we decide the results are significant.
284*58b9f456SAndroid Build Coastguard Worker // And once we do, we report those last results and exit.
285*58b9f456SAndroid Build Coastguard Worker // Please do note that the if there are repetitions, the iteration count
286*58b9f456SAndroid Build Coastguard Worker // is *only* calculated for the *first* repetition, and other repetitions
287*58b9f456SAndroid Build Coastguard Worker // simply use that precomputed iteration count.
288*58b9f456SAndroid Build Coastguard Worker for (;;) {
289*58b9f456SAndroid Build Coastguard Worker i = DoNIterations();
290*58b9f456SAndroid Build Coastguard Worker
291*58b9f456SAndroid Build Coastguard Worker // Do we consider the results to be significant?
292*58b9f456SAndroid Build Coastguard Worker // If we are doing repetitions, and the first repetition was already done,
293*58b9f456SAndroid Build Coastguard Worker // it has calculated the correct iteration time, so we have run that very
294*58b9f456SAndroid Build Coastguard Worker // iteration count just now. No need to calculate anything. Just report.
295*58b9f456SAndroid Build Coastguard Worker // Else, the normal rules apply.
296*58b9f456SAndroid Build Coastguard Worker const bool results_are_significant = !is_the_first_repetition ||
297*58b9f456SAndroid Build Coastguard Worker has_explicit_iteration_count ||
298*58b9f456SAndroid Build Coastguard Worker ShouldReportIterationResults(i);
299*58b9f456SAndroid Build Coastguard Worker
300*58b9f456SAndroid Build Coastguard Worker if (results_are_significant) break; // Good, let's report them!
301*58b9f456SAndroid Build Coastguard Worker
302*58b9f456SAndroid Build Coastguard Worker // Nope, bad iteration. Let's re-estimate the hopefully-sufficient
303*58b9f456SAndroid Build Coastguard Worker // iteration count, and run the benchmark again...
304*58b9f456SAndroid Build Coastguard Worker
305*58b9f456SAndroid Build Coastguard Worker iters = PredictNumItersNeeded(i);
306*58b9f456SAndroid Build Coastguard Worker assert(iters > i.iters &&
307*58b9f456SAndroid Build Coastguard Worker "if we did more iterations than we want to do the next time, "
308*58b9f456SAndroid Build Coastguard Worker "then we should have accepted the current iteration run.");
309*58b9f456SAndroid Build Coastguard Worker }
310*58b9f456SAndroid Build Coastguard Worker
311*58b9f456SAndroid Build Coastguard Worker // Oh, one last thing, we need to also produce the 'memory measurements'..
312*58b9f456SAndroid Build Coastguard Worker MemoryManager::Result memory_result;
313*58b9f456SAndroid Build Coastguard Worker size_t memory_iterations = 0;
314*58b9f456SAndroid Build Coastguard Worker if (memory_manager != nullptr) {
315*58b9f456SAndroid Build Coastguard Worker // Only run a few iterations to reduce the impact of one-time
316*58b9f456SAndroid Build Coastguard Worker // allocations in benchmarks that are not properly managed.
317*58b9f456SAndroid Build Coastguard Worker memory_iterations = std::min<size_t>(16, iters);
318*58b9f456SAndroid Build Coastguard Worker memory_manager->Start();
319*58b9f456SAndroid Build Coastguard Worker std::unique_ptr<internal::ThreadManager> manager;
320*58b9f456SAndroid Build Coastguard Worker manager.reset(new internal::ThreadManager(1));
321*58b9f456SAndroid Build Coastguard Worker RunInThread(&b, memory_iterations, 0, manager.get());
322*58b9f456SAndroid Build Coastguard Worker manager->WaitForAllThreads();
323*58b9f456SAndroid Build Coastguard Worker manager.reset();
324*58b9f456SAndroid Build Coastguard Worker
325*58b9f456SAndroid Build Coastguard Worker memory_manager->Stop(&memory_result);
326*58b9f456SAndroid Build Coastguard Worker }
327*58b9f456SAndroid Build Coastguard Worker
328*58b9f456SAndroid Build Coastguard Worker // Ok, now actualy report.
329*58b9f456SAndroid Build Coastguard Worker BenchmarkReporter::Run report = CreateRunReport(
330*58b9f456SAndroid Build Coastguard Worker b, i.results, memory_iterations, memory_result, i.seconds);
331*58b9f456SAndroid Build Coastguard Worker
332*58b9f456SAndroid Build Coastguard Worker if (!report.error_occurred && b.complexity != oNone)
333*58b9f456SAndroid Build Coastguard Worker complexity_reports.push_back(report);
334*58b9f456SAndroid Build Coastguard Worker
335*58b9f456SAndroid Build Coastguard Worker run_results.non_aggregates.push_back(report);
336*58b9f456SAndroid Build Coastguard Worker }
337*58b9f456SAndroid Build Coastguard Worker };
338*58b9f456SAndroid Build Coastguard Worker
339*58b9f456SAndroid Build Coastguard Worker } // end namespace
340*58b9f456SAndroid Build Coastguard Worker
RunBenchmark(const benchmark::internal::BenchmarkInstance & b,std::vector<BenchmarkReporter::Run> * complexity_reports)341*58b9f456SAndroid Build Coastguard Worker RunResults RunBenchmark(
342*58b9f456SAndroid Build Coastguard Worker const benchmark::internal::BenchmarkInstance& b,
343*58b9f456SAndroid Build Coastguard Worker std::vector<BenchmarkReporter::Run>* complexity_reports) {
344*58b9f456SAndroid Build Coastguard Worker internal::BenchmarkRunner r(b, complexity_reports);
345*58b9f456SAndroid Build Coastguard Worker return r.get_results();
346*58b9f456SAndroid Build Coastguard Worker }
347*58b9f456SAndroid Build Coastguard Worker
348*58b9f456SAndroid Build Coastguard Worker } // end namespace internal
349*58b9f456SAndroid Build Coastguard Worker
350*58b9f456SAndroid Build Coastguard Worker } // end namespace benchmark
351