@@ -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 }
@@ -159,6 +161,7 @@ void RunInThread(const BenchmarkInstance* b, IterationCount iters,
159161 results.cpu_time_used += timer.cpu_time_used ();
160162 results.real_time_used += timer.real_time_used ();
161163 results.manual_time_used += timer.manual_time_used ();
164+ results.manual_time_used_pow2 += timer.manual_time_used_pow2 ();
162165 results.complexity_n += st.complexity_length_n ();
163166 internal::Increment (&results.counters , st.counters );
164167 }
@@ -286,6 +289,11 @@ BenchmarkRunner::BenchmarkRunner(
286289 min_time(FLAGS_benchmark_dry_run
287290 ? 0
288291 : ComputeMinTime(b_, parsed_benchtime_flag)),
292+ min_rel_accuracy(FLAGS_benchmark_dry_run
293+ ? std::numeric_limits<double >::max()
294+ : (!IsZero(b.min_rel_accuracy())
295+ ? b.min_rel_accuracy()
296+ : FLAGS_benchmark_min_rel_accuracy)),
289297 min_warmup_time(
290298 FLAGS_benchmark_dry_run
291299 ? 0
@@ -356,8 +364,10 @@ BenchmarkRunner::IterationResults BenchmarkRunner::DoNIterations() {
356364
357365 // Base decisions off of real time if requested by this benchmark.
358366 i.seconds = i.results .cpu_time_used ;
367+ i.seconds_pow2 = 0 ;
359368 if (b.use_manual_time ()) {
360369 i.seconds = i.results .manual_time_used ;
370+ i.seconds_pow2 = i.results .manual_time_used_pow2 ;
361371 } else if (b.use_real_time ()) {
362372 i.seconds = i.results .real_time_used ;
363373 }
@@ -378,6 +388,11 @@ IterationCount BenchmarkRunner::PredictNumItersNeeded(
378388 const bool is_significant = (i.seconds / GetMinTimeToApply ()) > 0.1 ;
379389 multiplier = is_significant ? multiplier : 10.0 ;
380390
391+ if (!IsZero (GetMinRelAccuracy ())) {
392+ multiplier =
393+ std::max (multiplier, GetRelAccuracy (i) * 1.4 / GetMinRelAccuracy ());
394+ }
395+
381396 // So what seems to be the sufficiently-large iteration count? Round up.
382397 const IterationCount max_next_iters = static_cast <IterationCount>(
383398 std::llround (std::max (multiplier * static_cast <double >(i.iters ),
@@ -395,14 +410,12 @@ bool BenchmarkRunner::ShouldReportIterationResults(
395410 // Either it has run for a sufficient amount of time
396411 // or because an error was reported.
397412 return (i.results .skipped_ != 0u ) || FLAGS_benchmark_dry_run ||
398- i.iters >= kMaxIterations || // Too many iterations already.
399- i.seconds >=
400- GetMinTimeToApply () || // The elapsed time is large enough.
401- // CPU time is specified but the elapsed real time greatly exceeds
402- // the minimum time.
403- // Note that user provided timers are except from this test.
404- ((i.results .real_time_used >= 5 * GetMinTimeToApply ()) &&
405- !b.use_manual_time ());
413+ // Too many iterations already.
414+ i.iters >= kMaxIterations ||
415+ // We have applied for enough time and the relative accuracy is good
416+ // enough. Relative accuracy is checked only for user provided timers.
417+ (HasSufficientTimeToApply (i) &&
418+ (!b.use_manual_time () || HasSufficientRelAccuracy (i)));
406419}
407420
408421double BenchmarkRunner::GetMinTimeToApply () const {
@@ -414,6 +427,28 @@ double BenchmarkRunner::GetMinTimeToApply() const {
414427 return warmup_done ? min_time : min_warmup_time;
415428}
416429
430+ double BenchmarkRunner::GetRelAccuracy (const IterationResults& i) const {
431+ return std::sqrt (i.seconds_pow2 -
432+ std::pow (i.seconds , 2 .) / static_cast <double >(i.iters )) /
433+ i.seconds ;
434+ }
435+
436+ bool BenchmarkRunner::HasSufficientTimeToApply (
437+ const IterationResults& i) const {
438+ return i.seconds >= GetMinTimeToApply () ||
439+ // CPU time is specified but the elapsed real time greatly exceeds
440+ // the minimum time.
441+ // Note that user provided timers are except from this test.
442+ (!b.use_manual_time () &&
443+ i.results .real_time_used >= 5 * GetMinTimeToApply ());
444+ }
445+
446+ bool BenchmarkRunner::HasSufficientRelAccuracy (
447+ const IterationResults& i) const {
448+ return (IsZero (GetMinRelAccuracy ()) ||
449+ ((GetRelAccuracy (i) <= GetMinRelAccuracy ()) && (i.iters >= 2 )));
450+ }
451+
417452void BenchmarkRunner::FinishWarmUp (const IterationCount& i) {
418453 warmup_done = true ;
419454 iters = i;
0 commit comments