in src/benchmarks/benchmark_linux.h [68:142]
void Run(size_t thread_count, uint64_t seconds_to_run,
AffinityPattern affinity, uint64_t dump_interval) {
threads_finished_ = 0;
threads_ready_ = 0;
start_running_ = false;
Setup(thread_count);
// Start threads
std::deque<std::thread> threads;
for(size_t i = 0; i < thread_count; ++i) {
threads.emplace_back(&Benchmark::entry, this, i, thread_count, affinity);
}
// Wait for threads to be ready
while(threads_ready_.load() < thread_count);
uint64_t unique_dump_id = __rdtsc();
if(dump_interval > 0) {
Dump(thread_count, 0, unique_dump_id, false);
}
VLOG(1) << "Starting benchmark.";
// Start the benchmark
uint64_t start = Environment::Get()->NowMicros();
start_running_.store(true, std::memory_order_release);
const uint64_t end = start + seconds_to_run * 1000000;
if(dump_interval > 0) {
uint64_t next_dump_ticks = 1000000 + start;
uint64_t next_dump_seconds = 1;
while(threads_finished_.load() < thread_count) {
Environment::Get()->Sleep(10);
uint64_t now = Environment::Get()->NowMicros();
if(end <= now) {
is_shutdown_.store(true, std::memory_order_release);
break;
}
if(now < next_dump_ticks) continue;
// Collect metrics after the experiment end.
unique_dump_id = __rdtsc();
Dump(thread_count, now - start, unique_dump_id, false);
// 'Schedule' next dump.
next_dump_seconds += dump_interval;
next_dump_ticks = next_dump_seconds * 1000000 + start;
}
} else {
// Sleep the required amount of time before setting the shutdown flag.
Environment::Get()->Sleep((uint64_t)seconds_to_run * 1000);
is_shutdown_.store(true, std::memory_order_release);
// Wait for all threads to finish their workload
while(threads_finished_.load() < thread_count) {
Environment::Get()->Sleep(10);
}
}
for(auto& thread : threads) {
thread.join();
}
while(0 == end_.load());
unique_dump_id = __rdtsc();
VLOG(1) << "Benchmark stopped.";
Dump(thread_count, end_ - start, unique_dump_id, true);
run_seconds_ = double(end_ - start) / double(1000000);
Teardown();
}