mirror of
https://github.com/google/benchmark.git
synced 2025-01-30 22:00:16 +08:00
Move thread classes out to clean up monolithic code (#554)
This commit is contained in:
parent
a9beffda0b
commit
674d0498b8
112
src/benchmark.cc
112
src/benchmark.cc
@ -29,10 +29,10 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
@ -46,7 +46,8 @@
|
|||||||
#include "re.h"
|
#include "re.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include "timers.h"
|
#include "thread_manager.h"
|
||||||
|
#include "thread_timer.h"
|
||||||
|
|
||||||
DEFINE_bool(benchmark_list_tests, false,
|
DEFINE_bool(benchmark_list_tests, false,
|
||||||
"Print a list of benchmarks. This option overrides all other "
|
"Print a list of benchmarks. This option overrides all other "
|
||||||
@ -110,113 +111,6 @@ namespace internal {
|
|||||||
|
|
||||||
void UseCharPointer(char const volatile*) {}
|
void UseCharPointer(char const volatile*) {}
|
||||||
|
|
||||||
class ThreadManager {
|
|
||||||
public:
|
|
||||||
ThreadManager(int num_threads)
|
|
||||||
: alive_threads_(num_threads), start_stop_barrier_(num_threads) {}
|
|
||||||
|
|
||||||
Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) {
|
|
||||||
return benchmark_mutex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StartStopBarrier() EXCLUDES(end_cond_mutex_) {
|
|
||||||
return start_stop_barrier_.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) {
|
|
||||||
start_stop_barrier_.removeThread();
|
|
||||||
if (--alive_threads_ == 0) {
|
|
||||||
MutexLock lock(end_cond_mutex_);
|
|
||||||
end_condition_.notify_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaitForAllThreads() EXCLUDES(end_cond_mutex_) {
|
|
||||||
MutexLock lock(end_cond_mutex_);
|
|
||||||
end_condition_.wait(lock.native_handle(),
|
|
||||||
[this]() { return alive_threads_ == 0; });
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct Result {
|
|
||||||
double real_time_used = 0;
|
|
||||||
double cpu_time_used = 0;
|
|
||||||
double manual_time_used = 0;
|
|
||||||
int64_t bytes_processed = 0;
|
|
||||||
int64_t items_processed = 0;
|
|
||||||
int complexity_n = 0;
|
|
||||||
std::string report_label_;
|
|
||||||
std::string error_message_;
|
|
||||||
bool has_error_ = false;
|
|
||||||
UserCounters counters;
|
|
||||||
};
|
|
||||||
GUARDED_BY(GetBenchmarkMutex()) Result results;
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable Mutex benchmark_mutex_;
|
|
||||||
std::atomic<int> alive_threads_;
|
|
||||||
Barrier start_stop_barrier_;
|
|
||||||
Mutex end_cond_mutex_;
|
|
||||||
Condition end_condition_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Timer management class
|
|
||||||
class ThreadTimer {
|
|
||||||
public:
|
|
||||||
ThreadTimer() = default;
|
|
||||||
|
|
||||||
// Called by each thread
|
|
||||||
void StartTimer() {
|
|
||||||
running_ = true;
|
|
||||||
start_real_time_ = ChronoClockNow();
|
|
||||||
start_cpu_time_ = ThreadCPUUsage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by each thread
|
|
||||||
void StopTimer() {
|
|
||||||
CHECK(running_);
|
|
||||||
running_ = false;
|
|
||||||
real_time_used_ += ChronoClockNow() - start_real_time_;
|
|
||||||
// Floating point error can result in the subtraction producing a negative
|
|
||||||
// time. Guard against that.
|
|
||||||
cpu_time_used_ += std::max<double>(ThreadCPUUsage() - start_cpu_time_, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by each thread
|
|
||||||
void SetIterationTime(double seconds) { manual_time_used_ += seconds; }
|
|
||||||
|
|
||||||
bool running() const { return running_; }
|
|
||||||
|
|
||||||
// REQUIRES: timer is not running
|
|
||||||
double real_time_used() {
|
|
||||||
CHECK(!running_);
|
|
||||||
return real_time_used_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// REQUIRES: timer is not running
|
|
||||||
double cpu_time_used() {
|
|
||||||
CHECK(!running_);
|
|
||||||
return cpu_time_used_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// REQUIRES: timer is not running
|
|
||||||
double manual_time_used() {
|
|
||||||
CHECK(!running_);
|
|
||||||
return manual_time_used_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool running_ = false; // Is the timer running
|
|
||||||
double start_real_time_ = 0; // If running_
|
|
||||||
double start_cpu_time_ = 0; // If running_
|
|
||||||
|
|
||||||
// Accumulated time so far (does not contain current slice if running_)
|
|
||||||
double real_time_used_ = 0;
|
|
||||||
double cpu_time_used_ = 0;
|
|
||||||
// Manually set iteration time. User sets this with SetIterationTime(seconds).
|
|
||||||
double manual_time_used_ = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
BenchmarkReporter::Run CreateRunReport(
|
BenchmarkReporter::Run CreateRunReport(
|
||||||
|
62
src/thread_manager.h
Normal file
62
src/thread_manager.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef BENCHMARK_THREAD_MANAGER_H
|
||||||
|
#define BENCHMARK_THREAD_MANAGER_H
|
||||||
|
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
|
namespace benchmark {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
class ThreadManager {
|
||||||
|
public:
|
||||||
|
ThreadManager(int num_threads)
|
||||||
|
: alive_threads_(num_threads), start_stop_barrier_(num_threads) {}
|
||||||
|
|
||||||
|
Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) {
|
||||||
|
return benchmark_mutex_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartStopBarrier() EXCLUDES(end_cond_mutex_) {
|
||||||
|
return start_stop_barrier_.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) {
|
||||||
|
start_stop_barrier_.removeThread();
|
||||||
|
if (--alive_threads_ == 0) {
|
||||||
|
MutexLock lock(end_cond_mutex_);
|
||||||
|
end_condition_.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForAllThreads() EXCLUDES(end_cond_mutex_) {
|
||||||
|
MutexLock lock(end_cond_mutex_);
|
||||||
|
end_condition_.wait(lock.native_handle(),
|
||||||
|
[this]() { return alive_threads_ == 0; });
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Result {
|
||||||
|
double real_time_used = 0;
|
||||||
|
double cpu_time_used = 0;
|
||||||
|
double manual_time_used = 0;
|
||||||
|
int64_t bytes_processed = 0;
|
||||||
|
int64_t items_processed = 0;
|
||||||
|
int complexity_n = 0;
|
||||||
|
std::string report_label_;
|
||||||
|
std::string error_message_;
|
||||||
|
bool has_error_ = false;
|
||||||
|
UserCounters counters;
|
||||||
|
};
|
||||||
|
GUARDED_BY(GetBenchmarkMutex()) Result results;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Mutex benchmark_mutex_;
|
||||||
|
std::atomic<int> alive_threads_;
|
||||||
|
Barrier start_stop_barrier_;
|
||||||
|
Mutex end_cond_mutex_;
|
||||||
|
Condition end_condition_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace benchmark
|
||||||
|
|
||||||
|
#endif // BENCHMARK_THREAD_MANAGER_H
|
69
src/thread_timer.h
Normal file
69
src/thread_timer.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef BENCHMARK_THREAD_TIMER_H
|
||||||
|
#define BENCHMARK_THREAD_TIMER_H
|
||||||
|
|
||||||
|
#include "check.h"
|
||||||
|
#include "timers.h"
|
||||||
|
|
||||||
|
namespace benchmark {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
class ThreadTimer {
|
||||||
|
public:
|
||||||
|
ThreadTimer() = default;
|
||||||
|
|
||||||
|
// Called by each thread
|
||||||
|
void StartTimer() {
|
||||||
|
running_ = true;
|
||||||
|
start_real_time_ = ChronoClockNow();
|
||||||
|
start_cpu_time_ = ThreadCPUUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by each thread
|
||||||
|
void StopTimer() {
|
||||||
|
CHECK(running_);
|
||||||
|
running_ = false;
|
||||||
|
real_time_used_ += ChronoClockNow() - start_real_time_;
|
||||||
|
// Floating point error can result in the subtraction producing a negative
|
||||||
|
// time. Guard against that.
|
||||||
|
cpu_time_used_ += std::max<double>(ThreadCPUUsage() - start_cpu_time_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by each thread
|
||||||
|
void SetIterationTime(double seconds) { manual_time_used_ += seconds; }
|
||||||
|
|
||||||
|
bool running() const { return running_; }
|
||||||
|
|
||||||
|
// REQUIRES: timer is not running
|
||||||
|
double real_time_used() {
|
||||||
|
CHECK(!running_);
|
||||||
|
return real_time_used_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// REQUIRES: timer is not running
|
||||||
|
double cpu_time_used() {
|
||||||
|
CHECK(!running_);
|
||||||
|
return cpu_time_used_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// REQUIRES: timer is not running
|
||||||
|
double manual_time_used() {
|
||||||
|
CHECK(!running_);
|
||||||
|
return manual_time_used_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool running_ = false; // Is the timer running
|
||||||
|
double start_real_time_ = 0; // If running_
|
||||||
|
double start_cpu_time_ = 0; // If running_
|
||||||
|
|
||||||
|
// Accumulated time so far (does not contain current slice if running_)
|
||||||
|
double real_time_used_ = 0;
|
||||||
|
double cpu_time_used_ = 0;
|
||||||
|
// Manually set iteration time. User sets this with SetIterationTime(seconds).
|
||||||
|
double manual_time_used_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace benchmark
|
||||||
|
|
||||||
|
#endif // BENCHMARK_THREAD_TIMER_H
|
Loading…
Reference in New Issue
Block a user