mirror of
https://github.com/google/benchmark.git
synced 2025-02-06 09:10:30 +08:00
Previously the benchmark_test program executed the benchmark tests to make sure the API was working but was not checking the number of tests that were completed. If the regular expression matching breaks, zero tests could be ran. Similarly, if one of the APIs breaks and doesn't run the correct amount of tests then `make test` will catch this.
187 lines
4.8 KiB
C++
187 lines
4.8 KiB
C++
#include "benchmark/benchmark.h"
|
|
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
|
|
#include <iostream>
|
|
#include <limits>
|
|
#include <list>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <set>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
int ATTRIBUTE_NOINLINE Factorial(uint32_t n) {
|
|
return (n == 1) ? 1 : n * Factorial(n - 1);
|
|
}
|
|
|
|
double CalculatePi(int depth) {
|
|
double pi = 0.0;
|
|
for (int i = 0; i < depth; ++i) {
|
|
double numerator = static_cast<double>(((i % 2) * 2) - 1);
|
|
double denominator = static_cast<double>((2 * i) - 1);
|
|
pi += numerator / denominator;
|
|
}
|
|
return (pi - 1.0) * 4;
|
|
}
|
|
|
|
std::set<int> ConstructRandomSet(int size) {
|
|
std::set<int> s;
|
|
for (int i = 0; i < size; ++i)
|
|
s.insert(i);
|
|
return s;
|
|
}
|
|
|
|
std::mutex test_vector_mu;
|
|
std::vector<int>* test_vector = nullptr;
|
|
|
|
} // end namespace
|
|
|
|
#ifdef DEBUG
|
|
static void BM_Factorial(benchmark::State& state) {
|
|
int fac_42 = 0;
|
|
while (state.KeepRunning())
|
|
fac_42 = Factorial(8);
|
|
// Prevent compiler optimizations
|
|
CHECK(fac_42 != std::numeric_limits<int>::max());
|
|
}
|
|
BENCHMARK(BM_Factorial);
|
|
#endif
|
|
|
|
static void BM_CalculatePiRange(benchmark::State& state) {
|
|
double pi = 0.0;
|
|
while (state.KeepRunning())
|
|
pi = CalculatePi(state.range_x());
|
|
std::stringstream ss;
|
|
ss << pi;
|
|
state.SetLabel(ss.str());
|
|
}
|
|
BENCHMARK_RANGE(BM_CalculatePiRange, 1, 1024 * 1024);
|
|
|
|
static void BM_CalculatePi(benchmark::State& state) {
|
|
static const int depth = 1024;
|
|
double pi ATTRIBUTE_UNUSED = 0.0;
|
|
while (state.KeepRunning()) {
|
|
pi = CalculatePi(depth);
|
|
}
|
|
}
|
|
BENCHMARK(BM_CalculatePi)->Threads(8);
|
|
BENCHMARK(BM_CalculatePi)->ThreadRange(1, 32);
|
|
BENCHMARK(BM_CalculatePi)->ThreadPerCpu();
|
|
|
|
static void BM_SetInsert(benchmark::State& state) {
|
|
while (state.KeepRunning()) {
|
|
state.PauseTiming();
|
|
std::set<int> data = ConstructRandomSet(state.range_x());
|
|
state.ResumeTiming();
|
|
for (int j = 0; j < state.range_y(); ++j)
|
|
data.insert(rand());
|
|
}
|
|
state.SetItemsProcessed(state.iterations() * state.range_y());
|
|
state.SetBytesProcessed(state.iterations() * state.range_y() * sizeof(int));
|
|
}
|
|
BENCHMARK(BM_SetInsert)->RangePair(1<<10,8<<10, 1,10);
|
|
|
|
template<typename Q>
|
|
static void BM_Sequential(benchmark::State& state) {
|
|
typename Q::value_type v = 42;
|
|
while (state.KeepRunning()) {
|
|
Q q;
|
|
for (int i = state.range_x(); --i; )
|
|
q.push_back(v);
|
|
}
|
|
const int64_t items_processed =
|
|
static_cast<int64_t>(state.iterations()) * state.range_x();
|
|
state.SetItemsProcessed(items_processed);
|
|
state.SetBytesProcessed(items_processed * sizeof(v));
|
|
}
|
|
BENCHMARK_TEMPLATE(BM_Sequential, std::vector<int>)->Range(1 << 0, 1 << 10);
|
|
BENCHMARK_TEMPLATE(BM_Sequential, std::list<int>)->Range(1 << 0, 1 << 10);
|
|
|
|
static void BM_StringCompare(benchmark::State& state) {
|
|
std::string s1(state.range_x(), '-');
|
|
std::string s2(state.range_x(), '-');
|
|
int r = 0;
|
|
while (state.KeepRunning())
|
|
r |= s1.compare(s2);
|
|
// Prevent compiler optimizations
|
|
CHECK(r != std::numeric_limits<int>::max());
|
|
}
|
|
BENCHMARK(BM_StringCompare)->Range(1, 1<<20);
|
|
|
|
static void BM_SetupTeardown(benchmark::State& state) {
|
|
if (state.thread_index == 0) {
|
|
// No need to lock test_vector_mu here as this is running single-threaded.
|
|
test_vector = new std::vector<int>();
|
|
}
|
|
int i = 0;
|
|
while (state.KeepRunning()) {
|
|
std::lock_guard<std::mutex> l(test_vector_mu);
|
|
if (i%2 == 0)
|
|
test_vector->push_back(i);
|
|
else
|
|
test_vector->pop_back();
|
|
++i;
|
|
}
|
|
if (state.thread_index == 0) {
|
|
delete test_vector;
|
|
}
|
|
}
|
|
BENCHMARK(BM_SetupTeardown)->ThreadPerCpu();
|
|
|
|
static void BM_LongTest(benchmark::State& state) {
|
|
double tracker = 0.0;
|
|
while (state.KeepRunning())
|
|
for (int i = 0; i < state.range_x(); ++i)
|
|
tracker += i;
|
|
CHECK(tracker != 0.0);
|
|
}
|
|
BENCHMARK(BM_LongTest)->Range(1<<16,1<<28);
|
|
|
|
class TestReporter : public benchmark::internal::ConsoleReporter {
|
|
public:
|
|
virtual bool ReportContext(const Context& context) const {
|
|
return ConsoleReporter::ReportContext(context);
|
|
};
|
|
|
|
virtual void ReportRuns(const std::vector<Run>& report) const {
|
|
++count_;
|
|
ConsoleReporter::ReportRuns(report);
|
|
};
|
|
|
|
TestReporter() : count_(0) {}
|
|
|
|
virtual ~TestReporter() {}
|
|
|
|
int GetCount() const {
|
|
return count_;
|
|
}
|
|
|
|
private:
|
|
mutable size_t count_;
|
|
};
|
|
|
|
int main(int argc, const char* argv[]) {
|
|
benchmark::Initialize(&argc, argv);
|
|
|
|
CHECK(Factorial(8) == 40320);
|
|
CHECK(CalculatePi(1) == 0.0);
|
|
|
|
TestReporter test_reporter;
|
|
benchmark::RunSpecifiedBenchmarks(&test_reporter);
|
|
|
|
// Make sure we ran all of the tests
|
|
const size_t count = test_reporter.GetCount();
|
|
const size_t expected = (argc == 2) ? std::stoul(argv[1]) : count;
|
|
if (count != expected) {
|
|
std::cerr << "ERROR: Expected " << expected << " tests to be ran but only "
|
|
<< count << " completed" << std::endl;
|
|
return -1;
|
|
}
|
|
}
|
|
|