Merge pull request #92 from google/pimpl-benchmark

Pimpl the benchmark object to reduce dependencies on the STL.
This commit is contained in:
Eric 2015-03-17 12:17:53 -04:00
commit 957a3e339e
2 changed files with 104 additions and 53 deletions

View File

@ -163,7 +163,7 @@ void RunSpecifiedBenchmarks(const BenchmarkReporter* reporter = NULL);
namespace internal { namespace internal {
class Benchmark; class Benchmark;
class BenchmarkFamilies; class BenchmarkImp;
} }
// State is passed to a running Benchmark and contains state for the // State is passed to a running Benchmark and contains state for the
@ -452,27 +452,11 @@ class Benchmark {
// Equivalent to ThreadRange(NumCPUs(), NumCPUs()) // Equivalent to ThreadRange(NumCPUs(), NumCPUs())
Benchmark* ThreadPerCpu(); Benchmark* ThreadPerCpu();
// -------------------------------
// Following methods are not useful for clients
// Used inside the benchmark implementation // Used inside the benchmark implementation
struct Instance; struct Instance;
private: private:
std::string name_; BenchmarkImp* imp_;
Function* function_;
std::size_t registration_index_;
int arg_count_;
std::vector< std::pair<int, int> > args_; // Args for all benchmark runs
std::vector<int> thread_counts_;
// Special value placed in thread_counts_ to stand for NumCPUs()
static const int kNumCpuMarker = -1;
static void AddRange(std::vector<int>* dst, int lo, int hi, int mult);
friend class BenchmarkFamilies;
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(Benchmark); BENCHMARK_DISALLOW_COPY_AND_ASSIGN(Benchmark);
}; };

View File

@ -339,7 +339,6 @@ struct Benchmark::Instance {
bool multithreaded; // Is benchmark multi-threaded? bool multithreaded; // Is benchmark multi-threaded?
}; };
// Class for managing registered benchmarks. Note that each registered // Class for managing registered benchmarks. Note that each registered
// benchmark identifies a family of related benchmarks to run. // benchmark identifies a family of related benchmarks to run.
class BenchmarkFamilies { class BenchmarkFamilies {
@ -347,7 +346,7 @@ class BenchmarkFamilies {
static BenchmarkFamilies* GetInstance(); static BenchmarkFamilies* GetInstance();
// Registers a benchmark family and returns the index assigned to it. // Registers a benchmark family and returns the index assigned to it.
size_t AddBenchmark(Benchmark* family); size_t AddBenchmark(BenchmarkImp* family);
// Unregisters a family at the given index. // Unregisters a family at the given index.
void RemoveBenchmark(size_t index); void RemoveBenchmark(size_t index);
@ -360,11 +359,40 @@ class BenchmarkFamilies {
BenchmarkFamilies(); BenchmarkFamilies();
~BenchmarkFamilies(); ~BenchmarkFamilies();
std::vector<Benchmark*> families_; std::vector<BenchmarkImp*> families_;
Mutex mutex_; Mutex mutex_;
}; };
class BenchmarkImp {
public:
BenchmarkImp(const char* name, Function* func);
~BenchmarkImp();
void Arg(int x);
void Range(int start, int limit);
void DenseRange(int start, int limit);
void ArgPair(int start, int limit);
void RangePair(int lo1, int hi1, int lo2, int hi2);
void Threads(int t);
void ThreadRange(int min_threads, int max_threads);
void ThreadPerCpu();
static void AddRange(std::vector<int>* dst, int lo, int hi, int mult);
private:
friend class BenchmarkFamilies;
std::string name_;
Function* function_;
int arg_count_;
std::vector< std::pair<int, int> > args_; // Args for all benchmark runs
std::vector<int> thread_counts_;
std::size_t registration_index_;
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(BenchmarkImp);
};
BenchmarkFamilies* BenchmarkFamilies::GetInstance() { BenchmarkFamilies* BenchmarkFamilies::GetInstance() {
static BenchmarkFamilies instance; static BenchmarkFamilies instance;
return &instance; return &instance;
@ -373,12 +401,12 @@ BenchmarkFamilies* BenchmarkFamilies::GetInstance() {
BenchmarkFamilies::BenchmarkFamilies() { } BenchmarkFamilies::BenchmarkFamilies() { }
BenchmarkFamilies::~BenchmarkFamilies() { BenchmarkFamilies::~BenchmarkFamilies() {
for (internal::Benchmark* family : families_) { for (BenchmarkImp* family : families_) {
delete family; delete family;
} }
} }
size_t BenchmarkFamilies::AddBenchmark(Benchmark* family) { size_t BenchmarkFamilies::AddBenchmark(BenchmarkImp* family) {
MutexLock l(mutex_); MutexLock l(mutex_);
// This loop attempts to reuse an entry that was previously removed to avoid // This loop attempts to reuse an entry that was previously removed to avoid
// unncessary growth of the vector. // unncessary growth of the vector.
@ -416,7 +444,7 @@ bool BenchmarkFamilies::FindBenchmarks(
one_thread.push_back(1); one_thread.push_back(1);
MutexLock l(mutex_); MutexLock l(mutex_);
for (Benchmark* family : families_) { for (BenchmarkImp* family : families_) {
// Family was deleted or benchmark doesn't match // Family was deleted or benchmark doesn't match
if (family == nullptr || !re.Match(family->name_)) continue; if (family == nullptr || !re.Match(family->name_)) continue;
@ -461,25 +489,22 @@ bool BenchmarkFamilies::FindBenchmarks(
return true; return true;
} }
BenchmarkImp::BenchmarkImp(const char* name, Function* func)
Benchmark::Benchmark(const char* name, : name_(name), function_(func), arg_count_(-1) {
Function* f)
: name_(name), function_(f), arg_count_(-1) {
registration_index_ = BenchmarkFamilies::GetInstance()->AddBenchmark(this); registration_index_ = BenchmarkFamilies::GetInstance()->AddBenchmark(this);
} }
Benchmark::~Benchmark() { BenchmarkImp::~BenchmarkImp() {
BenchmarkFamilies::GetInstance()->RemoveBenchmark(registration_index_); BenchmarkFamilies::GetInstance()->RemoveBenchmark(registration_index_);
} }
Benchmark* Benchmark::Arg(int x) { void BenchmarkImp::Arg(int x) {
CHECK(arg_count_ == -1 || arg_count_ == 1); CHECK(arg_count_ == -1 || arg_count_ == 1);
arg_count_ = 1; arg_count_ = 1;
args_.emplace_back(x, -1); args_.emplace_back(x, -1);
return this;
} }
Benchmark* Benchmark::Range(int start, int limit) { void BenchmarkImp::Range(int start, int limit) {
CHECK(arg_count_ == -1 || arg_count_ == 1); CHECK(arg_count_ == -1 || arg_count_ == 1);
arg_count_ = 1; arg_count_ = 1;
std::vector<int> arglist; std::vector<int> arglist;
@ -488,10 +513,9 @@ Benchmark* Benchmark::Range(int start, int limit) {
for (int i : arglist) { for (int i : arglist) {
args_.emplace_back(i, -1); args_.emplace_back(i, -1);
} }
return this;
} }
Benchmark* Benchmark::DenseRange(int start, int limit) { void BenchmarkImp::DenseRange(int start, int limit) {
CHECK(arg_count_ == -1 || arg_count_ == 1); CHECK(arg_count_ == -1 || arg_count_ == 1);
arg_count_ = 1; arg_count_ = 1;
CHECK_GE(start, 0); CHECK_GE(start, 0);
@ -499,17 +523,15 @@ Benchmark* Benchmark::DenseRange(int start, int limit) {
for (int arg = start; arg <= limit; arg++) { for (int arg = start; arg <= limit; arg++) {
args_.emplace_back(arg, -1); args_.emplace_back(arg, -1);
} }
return this;
} }
Benchmark* Benchmark::ArgPair(int x, int y) { void BenchmarkImp::ArgPair(int x, int y) {
CHECK(arg_count_ == -1 || arg_count_ == 2); CHECK(arg_count_ == -1 || arg_count_ == 2);
arg_count_ = 2; arg_count_ = 2;
args_.emplace_back(x, y); args_.emplace_back(x, y);
return this;
} }
Benchmark* Benchmark::RangePair(int lo1, int hi1, int lo2, int hi2) { void BenchmarkImp::RangePair(int lo1, int hi1, int lo2, int hi2) {
CHECK(arg_count_ == -1 || arg_count_ == 2); CHECK(arg_count_ == -1 || arg_count_ == 2);
arg_count_ = 2; arg_count_ = 2;
std::vector<int> arglist1, arglist2; std::vector<int> arglist1, arglist2;
@ -521,35 +543,26 @@ Benchmark* Benchmark::RangePair(int lo1, int hi1, int lo2, int hi2) {
args_.emplace_back(i, j); args_.emplace_back(i, j);
} }
} }
return this;
} }
Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) { void BenchmarkImp::Threads(int t) {
custom_arguments(this);
return this;
}
Benchmark* Benchmark::Threads(int t) {
CHECK_GT(t, 0); CHECK_GT(t, 0);
thread_counts_.push_back(t); thread_counts_.push_back(t);
return this;
} }
Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) { void BenchmarkImp::ThreadRange(int min_threads, int max_threads) {
CHECK_GT(min_threads, 0); CHECK_GT(min_threads, 0);
CHECK_GE(max_threads, min_threads); CHECK_GE(max_threads, min_threads);
AddRange(&thread_counts_, min_threads, max_threads, 2); AddRange(&thread_counts_, min_threads, max_threads, 2);
return this;
} }
Benchmark* Benchmark::ThreadPerCpu() { void BenchmarkImp::ThreadPerCpu() {
static int num_cpus = NumCPUs(); static int num_cpus = NumCPUs();
thread_counts_.push_back(num_cpus); thread_counts_.push_back(num_cpus);
return this;
} }
void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) { void BenchmarkImp::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
CHECK_GE(lo, 0); CHECK_GE(lo, 0);
CHECK_GE(hi, lo); CHECK_GE(hi, lo);
@ -571,6 +584,60 @@ void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
} }
} }
Benchmark::Benchmark(const char* name, Function* f)
: imp_(new BenchmarkImp(name, f))
{
}
Benchmark::~Benchmark() {
delete imp_;
}
Benchmark* Benchmark::Arg(int x) {
imp_->Arg(x);
return this;
}
Benchmark* Benchmark::Range(int start, int limit) {
imp_->Range(start, limit);
return this;
}
Benchmark* Benchmark::DenseRange(int start, int limit) {
imp_->DenseRange(start, limit);
return this;
}
Benchmark* Benchmark::ArgPair(int x, int y) {
imp_->ArgPair(x, y);
return this;
}
Benchmark* Benchmark::RangePair(int lo1, int hi1, int lo2, int hi2) {
imp_->RangePair(lo1, hi1, lo2, hi2);
return this;
}
Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) {
custom_arguments(this);
return this;
}
Benchmark* Benchmark::Threads(int t) {
imp_->Threads(t);
return this;
}
Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
imp_->ThreadRange(min_threads, max_threads);
return this;
}
Benchmark* Benchmark::ThreadPerCpu() {
imp_->ThreadPerCpu();
return this;
}
} // end namespace internal } // end namespace internal
namespace { namespace {