@@ -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 }
@@ -154,6 +156,7 @@ void RunInThread(const BenchmarkInstance* b, IterationCount iters,
154156 results.cpu_time_used += timer.cpu_time_used ();
155157 results.real_time_used += timer.real_time_used ();
156158 results.manual_time_used += timer.manual_time_used ();
159+ results.manual_time_used_pow2 += timer.manual_time_used_pow2 ();
157160 results.complexity_n += st.complexity_length_n ();
158161 internal::Increment (&results.counters , st.counters );
159162 }
@@ -280,6 +283,11 @@ BenchmarkRunner::BenchmarkRunner(
280283 min_time(FLAGS_benchmark_dry_run
281284 ? 0
282285 : ComputeMinTime(b_, parsed_benchtime_flag)),
286+ min_rel_accuracy(FLAGS_benchmark_dry_run
287+ ? std::numeric_limits<double >::max()
288+ : (!IsZero(b.min_rel_accuracy())
289+ ? b.min_rel_accuracy()
290+ : FLAGS_benchmark_min_rel_accuracy)),
283291 min_warmup_time(
284292 FLAGS_benchmark_dry_run
285293 ? 0
@@ -350,8 +358,10 @@ BenchmarkRunner::IterationResults BenchmarkRunner::DoNIterations() {
350358
351359 // Base decisions off of real time if requested by this benchmark.
352360 i.seconds = i.results .cpu_time_used ;
361+ i.seconds_pow2 = 0 ;
353362 if (b.use_manual_time ()) {
354363 i.seconds = i.results .manual_time_used ;
364+ i.seconds_pow2 = i.results .manual_time_used_pow2 ;
355365 } else if (b.use_real_time ()) {
356366 i.seconds = i.results .real_time_used ;
357367 }
@@ -372,6 +382,11 @@ IterationCount BenchmarkRunner::PredictNumItersNeeded(
372382 const bool is_significant = (i.seconds / GetMinTimeToApply ()) > 0.1 ;
373383 multiplier = is_significant ? multiplier : 10.0 ;
374384
385+ if (!IsZero (GetMinRelAccuracy ())) {
386+ multiplier =
387+ std::max (multiplier, GetRelAccuracy (i) * 1.4 / GetMinRelAccuracy ());
388+ }
389+
375390 // So what seems to be the sufficiently-large iteration count? Round up.
376391 const IterationCount max_next_iters = static_cast <IterationCount>(
377392 std::llround (std::max (multiplier * static_cast <double >(i.iters ),
@@ -389,14 +404,12 @@ bool BenchmarkRunner::ShouldReportIterationResults(
389404 // Either it has run for a sufficient amount of time
390405 // or because an error was reported.
391406 return (i.results .skipped_ != 0u ) || FLAGS_benchmark_dry_run ||
392- i.iters >= kMaxIterations || // Too many iterations already.
393- i.seconds >=
394- GetMinTimeToApply () || // The elapsed time is large enough.
395- // CPU time is specified but the elapsed real time greatly exceeds
396- // the minimum time.
397- // Note that user provided timers are except from this test.
398- ((i.results .real_time_used >= 5 * GetMinTimeToApply ()) &&
399- !b.use_manual_time ());
407+ // Too many iterations already.
408+ i.iters >= kMaxIterations ||
409+ // We have applied for enough time and the relative accuracy is good
410+ // enough. Relative accuracy is checked only for user provided timers.
411+ (HasSufficientTimeToApply (i) &&
412+ (!b.use_manual_time () || HasSufficientRelAccuracy (i)));
400413}
401414
402415double BenchmarkRunner::GetMinTimeToApply () const {
@@ -408,6 +421,26 @@ double BenchmarkRunner::GetMinTimeToApply() const {
408421 return warmup_done ? min_time : min_warmup_time;
409422}
410423
424+ double BenchmarkRunner::GetRelAccuracy (const IterationResults& i) const {
425+ return std::sqrt (i.seconds_pow2 - std::pow (i.seconds , 2 .) / static_cast <double >(i.iters )) / i.seconds ;
426+ }
427+
428+ bool BenchmarkRunner::HasSufficientTimeToApply (
429+ const IterationResults& i) const {
430+ return i.seconds >= GetMinTimeToApply () ||
431+ // CPU time is specified but the elapsed real time greatly exceeds
432+ // the minimum time.
433+ // Note that user provided timers are except from this test.
434+ (!b.use_manual_time () &&
435+ i.results .real_time_used >= 5 * GetMinTimeToApply ());
436+ }
437+
438+ bool BenchmarkRunner::HasSufficientRelAccuracy (
439+ const IterationResults& i) const {
440+ return (IsZero (GetMinRelAccuracy ()) ||
441+ (GetRelAccuracy (i) <= GetMinRelAccuracy ()));
442+ }
443+
411444void BenchmarkRunner::FinishWarmUp (const IterationCount& i) {
412445 warmup_done = true ;
413446 iters = i;
0 commit comments