3333#include < cstdlib>
3434#include < fstream>
3535#include < iostream>
36+ #include < limits>
3637#include < map>
3738#include < memory>
39+ #include < random>
3840#include < string>
3941#include < thread>
4042#include < utility>
@@ -73,6 +75,10 @@ DEFINE_double(benchmark_min_time, 0.5);
7375// standard deviation of the runs will be reported.
7476DEFINE_int32 (benchmark_repetitions, 1 );
7577
78+ // If set, enable random interleaving of repetitions of all benchmarks.
79+ // See http://github.com/google/benchmark/issues/1051 for details.
80+ DEFINE_bool (benchmark_enable_random_interleaving, false );
81+
7682// Report the result of each benchmark repetitions. When 'true' is specified
7783// only the mean, standard deviation, and other statistics are reported for
7884// repeated benchmarks. Affects all reporters.
@@ -297,23 +303,69 @@ void RunBenchmarks(const std::vector<BenchmarkInstance>& benchmarks,
297303 context.name_field_width = name_field_width;
298304
299305 // Keep track of running times of all instances of each benchmark family.
300- std::map<int /* family_index*/ , std::vector< BenchmarkReporter::Run> >
301- complexity_reports ;
306+ std::map<int /* family_index*/ , BenchmarkReporter::PerFamilyRunReports >
307+ per_family_reports ;
302308
303309 if (display_reporter->ReportContext (context) &&
304310 (!file_reporter || file_reporter->ReportContext (context))) {
305311 FlushStreams (display_reporter);
306312 FlushStreams (file_reporter);
307313
314+ size_t num_repetitions_total = 0 ;
315+
316+ std::vector<internal::BenchmarkRunner> runners;
317+ runners.reserve (benchmarks.size ());
308318 for (const BenchmarkInstance& benchmark : benchmarks) {
309- std::vector<BenchmarkReporter::Run>* complexity_reports_for_family =
310- nullptr ;
319+ BenchmarkReporter::PerFamilyRunReports* reports_for_family = nullptr ;
311320 if (benchmark.complexity () != oNone)
312- complexity_reports_for_family =
313- &complexity_reports[benchmark.family_index ()];
321+ reports_for_family = &per_family_reports[benchmark.family_index ()];
322+
323+ runners.emplace_back (benchmark, reports_for_family);
324+ int num_repeats_of_this_instance = runners.back ().GetNumRepeats ();
325+ num_repetitions_total += num_repeats_of_this_instance;
326+ if (reports_for_family)
327+ reports_for_family->num_runs_total += num_repeats_of_this_instance;
328+ }
329+ assert (runners.size () == benchmarks.size () && " Unexpected runner count." );
330+
331+ std::vector<int > repetition_indices;
332+ repetition_indices.reserve (num_repetitions_total);
333+ for (size_t runner_index = 0 , num_runners = runners.size ();
334+ runner_index != num_runners; ++runner_index) {
335+ const internal::BenchmarkRunner& runner = runners[runner_index];
336+ std::fill_n (std::back_inserter (repetition_indices),
337+ runner.GetNumRepeats (), runner_index);
338+ }
339+ assert (repetition_indices.size () == num_repetitions_total &&
340+ " Unexpected number of repetition indexes." );
341+
342+ if (FLAGS_benchmark_enable_random_interleaving) {
343+ std::random_device rd;
344+ std::mt19937 g (rd ());
345+ std::shuffle (repetition_indices.begin (), repetition_indices.end (), g);
346+ }
314347
315- RunResults run_results =
316- RunBenchmark (benchmark, complexity_reports_for_family);
348+ for (size_t repetition_index : repetition_indices) {
349+ internal::BenchmarkRunner& runner = runners[repetition_index];
350+ runner.DoOneRepetition ();
351+ if (runner.HasRepeatsRemaining ()) continue ;
352+ // FIXME: report each repetition separately, not all of them in bulk.
353+
354+ RunResults run_results = runner.GetResults ();
355+
356+ // Maybe calculate complexity report
357+ if (BenchmarkReporter::PerFamilyRunReports* reports_for_family =
358+ runner.GetReportsForFamily ()) {
359+ if (reports_for_family->num_runs_done ==
360+ reports_for_family->num_runs_total ) {
361+ auto additional_run_stats = ComputeBigO (reports_for_family->Runs );
362+ run_results.aggregates_only .insert (run_results.aggregates_only .end (),
363+ additional_run_stats.begin (),
364+ additional_run_stats.end ());
365+ per_family_reports.erase (
366+ (int )reports_for_family->Runs .front ().family_index );
367+ }
368+ }
317369
318370 Report (display_reporter, file_reporter, run_results);
319371 }
@@ -471,6 +523,7 @@ void PrintUsageAndExit() {
471523 " [--benchmark_filter=<regex>]\n "
472524 " [--benchmark_min_time=<min_time>]\n "
473525 " [--benchmark_repetitions=<num_repetitions>]\n "
526+ " [--benchmark_enable_random_interleaving={true|false}]\n "
474527 " [--benchmark_report_aggregates_only={true|false}]\n "
475528 " [--benchmark_display_aggregates_only={true|false}]\n "
476529 " [--benchmark_format=<console|json|csv>]\n "
@@ -495,6 +548,8 @@ void ParseCommandLineFlags(int* argc, char** argv) {
495548 &FLAGS_benchmark_min_time) ||
496549 ParseInt32Flag (argv[i], " benchmark_repetitions" ,
497550 &FLAGS_benchmark_repetitions) ||
551+ ParseBoolFlag (argv[i], " benchmark_enable_random_interleaving" ,
552+ &FLAGS_benchmark_enable_random_interleaving) ||
498553 ParseBoolFlag (argv[i], " benchmark_report_aggregates_only" ,
499554 &FLAGS_benchmark_report_aggregates_only) ||
500555 ParseBoolFlag (argv[i], " benchmark_display_aggregates_only" ,
0 commit comments