@@ -60,6 +60,7 @@ namespace benchmark {
6060
6161BM_DECLARE_bool (benchmark_dry_run);
6262BM_DECLARE_string (benchmark_min_time);
63+ BM_DECLARE_double (benchmark_min_rel_accuracy);
6364BM_DECLARE_double (benchmark_min_warmup_time);
6465BM_DECLARE_int32 (benchmark_repetitions);
6566BM_DECLARE_bool (benchmark_report_aggregates_only);
@@ -103,6 +104,7 @@ BenchmarkReporter::Run CreateRunReport(
103104 if (report.skipped == 0u ) {
104105 if (b.use_manual_time ()) {
105106 report.real_accumulated_time = results.manual_time_used ;
107+ report.manual_accumulated_time_pow2 = results.manual_time_used_pow2 ;
106108 } else {
107109 report.real_accumulated_time = results.real_time_used ;
108110 }
@@ -151,6 +153,7 @@ void RunInThread(const BenchmarkInstance* b, IterationCount iters,
151153 results.cpu_time_used += timer.cpu_time_used ();
152154 results.real_time_used += timer.real_time_used ();
153155 results.manual_time_used += timer.manual_time_used ();
156+ results.manual_time_used_pow2 += timer.manual_time_used_pow2 ();
154157 results.complexity_n += st.complexity_length_n ();
155158 internal::Increment (&results.counters , st.counters );
156159 }
@@ -277,6 +280,11 @@ BenchmarkRunner::BenchmarkRunner(
277280 min_time(FLAGS_benchmark_dry_run
278281 ? 0
279282 : ComputeMinTime(b_, parsed_benchtime_flag)),
283+ min_rel_accuracy(FLAGS_benchmark_dry_run
284+ ? std::numeric_limits<double >::max()
285+ : (!IsZero(b.min_rel_accuracy())
286+ ? b.min_rel_accuracy()
287+ : FLAGS_benchmark_min_rel_accuracy)),
280288 min_warmup_time(
281289 FLAGS_benchmark_dry_run
282290 ? 0
@@ -347,8 +355,10 @@ BenchmarkRunner::IterationResults BenchmarkRunner::DoNIterations() {
347355
348356 // Base decisions off of real time if requested by this benchmark.
349357 i.seconds = i.results .cpu_time_used ;
358+ i.seconds_pow2 = 0 ;
350359 if (b.use_manual_time ()) {
351360 i.seconds = i.results .manual_time_used ;
361+ i.seconds_pow2 = i.results .manual_time_used_pow2 ;
352362 } else if (b.use_real_time ()) {
353363 i.seconds = i.results .real_time_used ;
354364 }
@@ -369,6 +379,11 @@ IterationCount BenchmarkRunner::PredictNumItersNeeded(
369379 const bool is_significant = (i.seconds / GetMinTimeToApply ()) > 0.1 ;
370380 multiplier = is_significant ? multiplier : 10.0 ;
371381
382+ if (!IsZero (GetMinRelAccuracy ())) {
383+ multiplier =
384+ std::max (multiplier, GetRelAccuracy (i) * 1.4 / GetMinRelAccuracy ());
385+ }
386+
372387 // So what seems to be the sufficiently-large iteration count? Round up.
373388 const IterationCount max_next_iters = static_cast <IterationCount>(
374389 std::llround (std::max (multiplier * static_cast <double >(i.iters ),
@@ -386,14 +401,12 @@ bool BenchmarkRunner::ShouldReportIterationResults(
386401 // Either it has run for a sufficient amount of time
387402 // or because an error was reported.
388403 return (i.results .skipped_ != 0u ) || FLAGS_benchmark_dry_run ||
389- i.iters >= kMaxIterations || // Too many iterations already.
390- i.seconds >=
391- GetMinTimeToApply () || // The elapsed time is large enough.
392- // CPU time is specified but the elapsed real time greatly exceeds
393- // the minimum time.
394- // Note that user provided timers are except from this test.
395- ((i.results .real_time_used >= 5 * GetMinTimeToApply ()) &&
396- !b.use_manual_time ());
404+ // Too many iterations already.
405+ i.iters >= kMaxIterations ||
406+ // We have applied for enough time and the relative accuracy is good
407+ // enough. Relative accuracy is checked only for user provided timers.
408+ (HasSufficientTimeToApply (i) &&
409+ (!b.use_manual_time () || HasSufficientRelAccuracy (i)));
397410}
398411
399412double BenchmarkRunner::GetMinTimeToApply () const {
@@ -405,6 +418,26 @@ double BenchmarkRunner::GetMinTimeToApply() const {
405418 return warmup_done ? min_time : min_warmup_time;
406419}
407420
421+ double BenchmarkRunner::GetRelAccuracy (const IterationResults& i) const {
422+ return std::sqrt (i.seconds_pow2 - std::pow (i.seconds , 2 .) / static_cast <double >(i.iters )) / i.seconds ;
423+ }
424+
425+ bool BenchmarkRunner::HasSufficientTimeToApply (
426+ const IterationResults& i) const {
427+ return i.seconds >= GetMinTimeToApply () ||
428+ // CPU time is specified but the elapsed real time greatly exceeds
429+ // the minimum time.
430+ // Note that user provided timers are except from this test.
431+ (!b.use_manual_time () &&
432+ i.results .real_time_used >= 5 * GetMinTimeToApply ());
433+ }
434+
435+ bool BenchmarkRunner::HasSufficientRelAccuracy (
436+ const IterationResults& i) const {
437+ return (IsZero (GetMinRelAccuracy ()) ||
438+ (GetRelAccuracy (i) <= GetMinRelAccuracy ()));
439+ }
440+
408441void BenchmarkRunner::FinishWarmUp (const IterationCount& i) {
409442 warmup_done = true ;
410443 iters = i;
0 commit comments