Commit 9d4b719d by Eric Committed by GitHub

Make Benchmark a single header library (but not header-only) (#407)

* Make Benchmark a single header library (but not header-only) This patch refactors benchmark into a single header, to allow for slightly easier usage. The initial reason for the header split was to keep C++ library components from being included by benchmark_api.h, making that part of the library STL agnostic. However this has since changed and there seems to be little reason to separate the reporters from the rest of the library. * Fix internal_macros.h * Remove more references to macros.h
parent 710c2b89
// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BENCHMARK_MACROS_H_
#define BENCHMARK_MACROS_H_
#if __cplusplus >= 201103L
#define BENCHMARK_HAS_CXX11
#endif
#ifndef BENCHMARK_HAS_CXX11
#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
TypeName& operator=(const TypeName&)
#else
#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
TypeName& operator=(const TypeName&) = delete
#endif
#if defined(__GNUC__)
#define BENCHMARK_UNUSED __attribute__((unused))
#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
#define BENCHMARK_NOEXCEPT noexcept
#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
#elif defined(_MSC_VER) && !defined(__clang__)
#define BENCHMARK_UNUSED
#define BENCHMARK_ALWAYS_INLINE __forceinline
#if _MSC_VER >= 1900
#define BENCHMARK_NOEXCEPT noexcept
#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
#else
#define BENCHMARK_NOEXCEPT
#define BENCHMARK_NOEXCEPT_OP(x)
#endif
#define __func__ __FUNCTION__
#else
#define BENCHMARK_UNUSED
#define BENCHMARK_ALWAYS_INLINE
#define BENCHMARK_NOEXCEPT
#define BENCHMARK_NOEXCEPT_OP(x)
#endif
#if defined(__GNUC__)
#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
#else
#define BENCHMARK_BUILTIN_EXPECT(x, y) x
#define BENCHMARK_DEPRECATED_MSG(msg)
#endif
#if defined(__GNUC__) && !defined(__clang__)
#define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#endif
#endif // BENCHMARK_MACROS_H_
......@@ -14,223 +14,14 @@
#ifndef BENCHMARK_REPORTER_H_
#define BENCHMARK_REPORTER_H_
#include <cassert>
#include <iosfwd>
#include <string>
#include <utility>
#include <vector>
#include <set>
#ifdef __DEPRECATED
# ifndef BENCHMARK_WARNING_MSG
# warning the reporter.h header has been deprecated and will be removed, please include benchmark.h instead
# else
BENCHMARK_WARNING_MSG("the reporter.h header has been deprecated and will be removed, please include benchmark.h instead")
# endif
#endif
#include "benchmark_api.h" // For forward declaration of BenchmarkReporter
#include "benchmark.h" // For forward declaration of BenchmarkReporter
namespace benchmark {
// Interface for custom benchmark result printers.
// By default, benchmark reports are printed to stdout. However an application
// can control the destination of the reports by calling
// RunSpecifiedBenchmarks and passing it a custom reporter object.
// The reporter object must implement the following interface.
class BenchmarkReporter {
public:
struct Context {
int num_cpus;
double mhz_per_cpu;
bool cpu_scaling_enabled;
// The number of chars in the longest benchmark name.
size_t name_field_width;
};
struct Run {
Run()
: error_occurred(false),
iterations(1),
time_unit(kNanosecond),
real_accumulated_time(0),
cpu_accumulated_time(0),
bytes_per_second(0),
items_per_second(0),
max_heapbytes_used(0),
complexity(oNone),
complexity_lambda(),
complexity_n(0),
report_big_o(false),
report_rms(false),
counters() {}
std::string benchmark_name;
std::string report_label; // Empty if not set by benchmark.
bool error_occurred;
std::string error_message;
int64_t iterations;
TimeUnit time_unit;
double real_accumulated_time;
double cpu_accumulated_time;
// Return a value representing the real time per iteration in the unit
// specified by 'time_unit'.
// NOTE: If 'iterations' is zero the returned value represents the
// accumulated time.
double GetAdjustedRealTime() const;
// Return a value representing the cpu time per iteration in the unit
// specified by 'time_unit'.
// NOTE: If 'iterations' is zero the returned value represents the
// accumulated time.
double GetAdjustedCPUTime() const;
// Zero if not set by benchmark.
double bytes_per_second;
double items_per_second;
// This is set to 0.0 if memory tracing is not enabled.
double max_heapbytes_used;
// Keep track of arguments to compute asymptotic complexity
BigO complexity;
BigOFunc* complexity_lambda;
int complexity_n;
// Inform print function whether the current run is a complexity report
bool report_big_o;
bool report_rms;
UserCounters counters;
};
// Construct a BenchmarkReporter with the output stream set to 'std::cout'
// and the error stream set to 'std::cerr'
BenchmarkReporter();
// Called once for every suite of benchmarks run.
// The parameter "context" contains information that the
// reporter may wish to use when generating its report, for example the
// platform under which the benchmarks are running. The benchmark run is
// never started if this function returns false, allowing the reporter
// to skip runs based on the context information.
virtual bool ReportContext(const Context& context) = 0;
// Called once for each group of benchmark runs, gives information about
// cpu-time and heap memory usage during the benchmark run. If the group
// of runs contained more than two entries then 'report' contains additional
// elements representing the mean and standard deviation of those runs.
// Additionally if this group of runs was the last in a family of benchmarks
// 'reports' contains additional entries representing the asymptotic
// complexity and RMS of that benchmark family.
virtual void ReportRuns(const std::vector<Run>& report) = 0;
// Called once and only once after ever group of benchmarks is run and
// reported.
virtual void Finalize() {}
// REQUIRES: The object referenced by 'out' is valid for the lifetime
// of the reporter.
void SetOutputStream(std::ostream* out) {
assert(out);
output_stream_ = out;
}
// REQUIRES: The object referenced by 'err' is valid for the lifetime
// of the reporter.
void SetErrorStream(std::ostream* err) {
assert(err);
error_stream_ = err;
}
std::ostream& GetOutputStream() const { return *output_stream_; }
std::ostream& GetErrorStream() const { return *error_stream_; }
virtual ~BenchmarkReporter();
// Write a human readable string to 'out' representing the specified
// 'context'.
// REQUIRES: 'out' is non-null.
static void PrintBasicContext(std::ostream* out, Context const& context);
private:
std::ostream* output_stream_;
std::ostream* error_stream_;
};
// Simple reporter that outputs benchmark data to the console. This is the
// default reporter used by RunSpecifiedBenchmarks().
class ConsoleReporter : public BenchmarkReporter {
public:
enum OutputOptions {
OO_None = 0,
OO_Color = 1,
OO_Tabular = 2,
OO_ColorTabular = OO_Color|OO_Tabular,
OO_Defaults = OO_ColorTabular
};
explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
: output_options_(opts_), name_field_width_(0),
prev_counters_(), printed_header_(false) {}
virtual bool ReportContext(const Context& context);
virtual void ReportRuns(const std::vector<Run>& reports);
protected:
virtual void PrintRunData(const Run& report);
virtual void PrintHeader(const Run& report);
OutputOptions output_options_;
size_t name_field_width_;
UserCounters prev_counters_;
bool printed_header_;
};
class JSONReporter : public BenchmarkReporter {
public:
JSONReporter() : first_report_(true) {}
virtual bool ReportContext(const Context& context);
virtual void ReportRuns(const std::vector<Run>& reports);
virtual void Finalize();
private:
void PrintRunData(const Run& report);
bool first_report_;
};
class CSVReporter : public BenchmarkReporter {
public:
CSVReporter() : printed_header_(false) {}
virtual bool ReportContext(const Context& context);
virtual void ReportRuns(const std::vector<Run>& reports);
private:
void PrintRunData(const Run& report);
bool printed_header_;
std::set< std::string > user_counter_names_;
};
inline const char* GetTimeUnitString(TimeUnit unit) {
switch (unit) {
case kMillisecond:
return "ms";
case kMicrosecond:
return "us";
case kNanosecond:
default:
return "ns";
}
}
inline double GetTimeUnitMultiplier(TimeUnit unit) {
switch (unit) {
case kMillisecond:
return 1e3;
case kMicrosecond:
return 1e6;
case kNanosecond:
default:
return 1e9;
}
}
} // end namespace benchmark
#endif // BENCHMARK_REPORTER_H_
#ifndef BENCHMARK_API_INTERNAL_H
#define BENCHMARK_API_INTERNAL_H
#include "benchmark/benchmark_api.h"
#include "benchmark/benchmark.h"
#include <cmath>
#include <iosfwd>
......
......@@ -15,7 +15,7 @@
// Source project : https://github.com/ismaelJimenez/cpp.leastsq
// Adapted to be used with google benchmark
#include "benchmark/benchmark_api.h"
#include "benchmark/benchmark.h"
#include <algorithm>
#include <cmath>
......
......@@ -21,8 +21,7 @@
#include <string>
#include <vector>
#include "benchmark/benchmark_api.h"
#include "benchmark/reporter.h"
#include "benchmark/benchmark.h"
namespace benchmark {
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "benchmark/reporter.h"
#include "benchmark/benchmark.h"
#include "complexity.h"
#include "counter.h"
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "benchmark/benchmark_api.h"
#include "benchmark/benchmark.h"
namespace benchmark {
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "benchmark/reporter.h"
#include "benchmark/benchmark.h"
#include "complexity.h"
#include <algorithm>
......
......@@ -23,7 +23,7 @@
#include <cstdint>
#include "benchmark/macros.h"
#include "benchmark/benchmark.h"
#include "internal_macros.h"
#if defined(BENCHMARK_OS_MACOSX)
......
#ifndef BENCHMARK_INTERNAL_MACROS_H_
#define BENCHMARK_INTERNAL_MACROS_H_
#include "benchmark/macros.h"
#include "benchmark/benchmark.h"
#ifndef __has_feature
#define __has_feature(x) 0
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "benchmark/reporter.h"
#include "benchmark/benchmark.h"
#include "complexity.h"
#include <algorithm>
......
......@@ -4,7 +4,7 @@
#include <iostream>
#include <ostream>
#include "benchmark/macros.h"
#include "benchmark/benchmark.h"
namespace benchmark {
namespace internal {
......@@ -70,4 +70,4 @@ inline LogType& GetLogInstanceForLevel(int level) {
(::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \
" ")
#endif
\ No newline at end of file
#endif
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "benchmark/reporter.h"
#include "benchmark/benchmark.h"
#include "timers.h"
#include <cstdlib>
......
#include "benchmark/benchmark_api.h"
#include "benchmark/benchmark.h"
#define BASIC_BENCHMARK_TEST(x) BENCHMARK(x)->Arg(8)->Arg(512)->Arg(8192)
......
......@@ -11,7 +11,7 @@
#include <stdexcept>
#include "../src/check.h"
#include "benchmark/benchmark_api.h"
#include "benchmark/benchmark.h"
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
#define TEST_HAS_NO_EXCEPTIONS
......
#include "benchmark/benchmark_api.h"
#include "benchmark/benchmark.h"
#include <chrono>
#include <thread>
......
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