Commit 27f0baa1 by Ismael

Added test file and Complexity() interface

parent 0a60062b
...@@ -231,6 +231,20 @@ enum TimeUnit { ...@@ -231,6 +231,20 @@ enum TimeUnit {
kMillisecond kMillisecond
}; };
// BigO is passed to a benchmark in order to specify the asymptotic computational
// complexity for the benchmark.
enum BigO {
O_None,
O_1,
O_N,
O_M_plus_N,
O_N_Squared,
O_N_Cubed,
O_log_N,
O_N_log_N,
O_Auto
};
// State is passed to a running Benchmark and contains state for the // State is passed to a running Benchmark and contains state for the
// benchmark to use. // benchmark to use.
class State { class State {
...@@ -465,6 +479,10 @@ public: ...@@ -465,6 +479,10 @@ public:
// to control how many iterations are run, and in the printing of items/second // to control how many iterations are run, and in the printing of items/second
// or MB/second values. // or MB/second values.
Benchmark* UseManualTime(); Benchmark* UseManualTime();
// Set the asymptotic computational complexity for the benchmark. This option
// called the asymptotic computational complexity will be shown on the output.
Benchmark* Complexity(BigO complexity);
// Support for running multiple copies of the same benchmark concurrently // Support for running multiple copies of the same benchmark concurrently
// in multiple threads. This may be useful when measuring the scaling // in multiple threads. This may be useful when measuring the scaling
......
...@@ -290,6 +290,7 @@ struct Benchmark::Instance { ...@@ -290,6 +290,7 @@ struct Benchmark::Instance {
int range_multiplier; int range_multiplier;
bool use_real_time; bool use_real_time;
bool use_manual_time; bool use_manual_time;
BigO complexity;
double min_time; double min_time;
int threads; // Number of concurrent threads to use int threads; // Number of concurrent threads to use
bool multithreaded; // Is benchmark multi-threaded? bool multithreaded; // Is benchmark multi-threaded?
...@@ -331,6 +332,7 @@ public: ...@@ -331,6 +332,7 @@ public:
void MinTime(double n); void MinTime(double n);
void UseRealTime(); void UseRealTime();
void UseManualTime(); void UseManualTime();
void Complexity(BigO complexity);
void Threads(int t); void Threads(int t);
void ThreadRange(int min_threads, int max_threads); void ThreadRange(int min_threads, int max_threads);
void ThreadPerCpu(); void ThreadPerCpu();
...@@ -349,6 +351,7 @@ private: ...@@ -349,6 +351,7 @@ private:
double min_time_; double min_time_;
bool use_real_time_; bool use_real_time_;
bool use_manual_time_; bool use_manual_time_;
BigO complexity_;
std::vector<int> thread_counts_; std::vector<int> thread_counts_;
BenchmarkImp& operator=(BenchmarkImp const&); BenchmarkImp& operator=(BenchmarkImp const&);
...@@ -411,6 +414,7 @@ bool BenchmarkFamilies::FindBenchmarks( ...@@ -411,6 +414,7 @@ bool BenchmarkFamilies::FindBenchmarks(
instance.min_time = family->min_time_; instance.min_time = family->min_time_;
instance.use_real_time = family->use_real_time_; instance.use_real_time = family->use_real_time_;
instance.use_manual_time = family->use_manual_time_; instance.use_manual_time = family->use_manual_time_;
instance.complexity = family->complexity_;
instance.threads = num_threads; instance.threads = num_threads;
instance.multithreaded = !(family->thread_counts_.empty()); instance.multithreaded = !(family->thread_counts_.empty());
...@@ -447,7 +451,8 @@ bool BenchmarkFamilies::FindBenchmarks( ...@@ -447,7 +451,8 @@ bool BenchmarkFamilies::FindBenchmarks(
BenchmarkImp::BenchmarkImp(const char* name) BenchmarkImp::BenchmarkImp(const char* name)
: name_(name), arg_count_(-1), time_unit_(kNanosecond), : name_(name), arg_count_(-1), time_unit_(kNanosecond),
range_multiplier_(kRangeMultiplier), min_time_(0.0), range_multiplier_(kRangeMultiplier), min_time_(0.0),
use_real_time_(false), use_manual_time_(false) { use_real_time_(false), use_manual_time_(false),
complexity_(O_None) {
} }
BenchmarkImp::~BenchmarkImp() { BenchmarkImp::~BenchmarkImp() {
...@@ -523,6 +528,10 @@ void BenchmarkImp::UseManualTime() { ...@@ -523,6 +528,10 @@ void BenchmarkImp::UseManualTime() {
use_manual_time_ = true; use_manual_time_ = true;
} }
void BenchmarkImp::Complexity(BigO complexity){
complexity_ = complexity;
}
void BenchmarkImp::Threads(int t) { void BenchmarkImp::Threads(int t) {
CHECK_GT(t, 0); CHECK_GT(t, 0);
thread_counts_.push_back(t); thread_counts_.push_back(t);
...@@ -636,6 +645,11 @@ Benchmark* Benchmark::UseManualTime() { ...@@ -636,6 +645,11 @@ Benchmark* Benchmark::UseManualTime() {
return this; return this;
} }
Benchmark* Benchmark::Complexity(BigO complexity) {
imp_->Complexity(complexity);
return this;
}
Benchmark* Benchmark::Threads(int t) { Benchmark* Benchmark::Threads(int t) {
imp_->Threads(t); imp_->Threads(t);
return this; return this;
......
...@@ -47,6 +47,9 @@ set_target_properties(cxx03_test ...@@ -47,6 +47,9 @@ set_target_properties(cxx03_test
PROPERTIES COMPILE_FLAGS "${CXX03_FLAGS}") PROPERTIES COMPILE_FLAGS "${CXX03_FLAGS}")
add_test(cxx03 cxx03_test --benchmark_min_time=0.01) add_test(cxx03 cxx03_test --benchmark_min_time=0.01)
compile_benchmark_test(complexity_test)
add_test(complexity_benchmark complexity_test --benchmark_min_time=0.01)
# Add the coverage command(s) # Add the coverage command(s)
if(CMAKE_BUILD_TYPE) if(CMAKE_BUILD_TYPE)
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
...@@ -66,7 +69,7 @@ if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage") ...@@ -66,7 +69,7 @@ if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage")
COMMAND ${LCOV} -q -a before.lcov -a after.lcov --output-file final.lcov COMMAND ${LCOV} -q -a before.lcov -a after.lcov --output-file final.lcov
COMMAND ${LCOV} -q -r final.lcov "'${CMAKE_SOURCE_DIR}/test/*'" -o final.lcov COMMAND ${LCOV} -q -r final.lcov "'${CMAKE_SOURCE_DIR}/test/*'" -o final.lcov
COMMAND ${GENHTML} final.lcov -o lcov --demangle-cpp --sort -p "${CMAKE_BINARY_DIR}" -t benchmark COMMAND ${GENHTML} final.lcov -o lcov --demangle-cpp --sort -p "${CMAKE_BINARY_DIR}" -t benchmark
DEPENDS filter_test benchmark_test options_test basic_test fixture_test cxx03_test DEPENDS filter_test benchmark_test options_test basic_test fixture_test cxx03_test complexity_test
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Running LCOV" COMMENT "Running LCOV"
) )
......
#include "benchmark/benchmark_api.h"
#include <string>
#include <vector>
#include <map>
#include <algorithm>
std::vector<int> ConstructRandomVector(int size) {
std::vector<int> v;
v.reserve(size);
for (int i = 0; i < size; ++i) {
v.push_back(rand() % size);
}
return v;
}
std::map<int, int> ConstructRandomMap(int size) {
std::map<int, int> m;
for (int i = 0; i < size; ++i) {
m.insert(std::make_pair(rand() % size, rand() % size));
}
return m;
}
void BM_Complexity_O1(benchmark::State& state) {
while (state.KeepRunning()) {
}
}
BENCHMARK(BM_Complexity_O1) -> Range(1, 1<<17) -> Complexity(benchmark::O_1);
static void BM_Complexity_O_N(benchmark::State& state) {
auto v = ConstructRandomVector(state.range_x());
const int itemNotInVector = state.range_x()*2; // Test worst case scenario (item not in vector)
while (state.KeepRunning()) {
benchmark::DoNotOptimize(std::find(v.begin(), v.end(), itemNotInVector));
}
}
BENCHMARK(BM_Complexity_O_N) -> Range(1, 1<<10) -> Complexity(benchmark::O_N);
BENCHMARK(BM_Complexity_O_N) -> Range(1, 1<<10) -> Complexity(benchmark::O_Auto);
static void BM_Complexity_O_M_plus_N(benchmark::State& state) {
std::string s1(state.range_x(), '-');
std::string s2(state.range_x(), '-');
while (state.KeepRunning())
benchmark::DoNotOptimize(s1.compare(s2));
}
BENCHMARK(BM_Complexity_O_M_plus_N)
->RangeMultiplier(2)->Range(1<<10, 1<<18) -> Complexity(benchmark::O_M_plus_N);
static void BM_Complexity_O_N_Squared(benchmark::State& state) {
std::string s1(state.range_x(), '-');
std::string s2(state.range_x(), '-');
while (state.KeepRunning())
for(char& c1 : s1) {
for(char& c2 : s2) {
benchmark::DoNotOptimize(c1 = 'a');
benchmark::DoNotOptimize(c2 = 'b');
}
}
}
BENCHMARK(BM_Complexity_O_N_Squared) -> Range(1, 1<<8) -> Complexity(benchmark::O_N_Squared);
static void BM_Complexity_O_N_Cubed(benchmark::State& state) {
std::string s1(state.range_x(), '-');
std::string s2(state.range_x(), '-');
std::string s3(state.range_x(), '-');
while (state.KeepRunning())
for(char& c1 : s1) {
for(char& c2 : s2) {
for(char& c3 : s3) {
benchmark::DoNotOptimize(c1 = 'a');
benchmark::DoNotOptimize(c2 = 'b');
benchmark::DoNotOptimize(c3 = 'c');
}
}
}
}
BENCHMARK(BM_Complexity_O_N_Cubed) -> DenseRange(1, 8) -> Complexity(benchmark::O_N_Cubed);
static void BM_Complexity_O_log_N(benchmark::State& state) {
auto m = ConstructRandomMap(state.range_x());
const int itemNotInVector = state.range_x()*2; // Test worst case scenario (item not in vector)
while (state.KeepRunning()) {
benchmark::DoNotOptimize(m.find(itemNotInVector));
}
}
BENCHMARK(BM_Complexity_O_log_N) -> Range(1, 1<<10) -> Complexity(benchmark::O_log_N);
static void BM_Complexity_O_N_log_N(benchmark::State& state) {
auto v = ConstructRandomVector(state.range_x());
while (state.KeepRunning()) {
std::sort(v.begin(), v.end());
}
}
BENCHMARK(BM_Complexity_O_N_log_N) -> Range(1, 1<<16) -> Complexity(benchmark::O_N_log_N);
BENCHMARK(BM_Complexity_O_N_log_N) -> Range(1, 1<<16) -> Complexity(benchmark::O_Auto);
// Test benchmark with no range. Complexity is always calculated as O(1).
void BM_Extreme_Cases(benchmark::State& state) {
while (state.KeepRunning()) {
}
}
BENCHMARK(BM_Extreme_Cases);
BENCHMARK(BM_Extreme_Cases)->Arg(42);
BENCHMARK_MAIN()
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment