Commit 40fce80e by Eric Fiselier

Merge branch 'upstream/master' into v2

parents e63fb496 296ec569
......@@ -45,6 +45,9 @@ rules.ninja
build/
_build/
# in-source dependancies
# in-source dependencies
/googletest/
# Visual Studio 2015/2017 cache/options directory
.vs/
CMakeSettings.json
......@@ -172,6 +172,7 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
#include <stdint.h>
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iosfwd>
......@@ -481,16 +482,18 @@ class State {
// Returns true if the benchmark should continue through another iteration.
// NOTE: A benchmark may not return from the test until KeepRunning() has
// returned false.
bool KeepRunning() {
if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
StartKeepRunning();
}
bool const res = (--total_iterations_ != 0);
if (BENCHMARK_BUILTIN_EXPECT(!res, false)) {
FinishKeepRunning();
}
return res;
}
bool KeepRunning();
// Returns true iff the benchmark should run n more iterations.
// NOTE: A benchmark must not return from the test until KeepRunningBatch()
// has returned false.
// NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations.
//
// Intended usage:
// while (state.KeepRunningBatch(1000)) {
// // process 1000 elements
// }
bool KeepRunningBatch(size_t n);
// REQUIRES: timer is running and 'SkipWithError(...)' has not been called
// by the current thread.
......@@ -635,12 +638,16 @@ class State {
int range_y() const { return range(1); }
BENCHMARK_ALWAYS_INLINE
size_t iterations() const { return (max_iterations - total_iterations_) + 1; }
size_t iterations() const {
return (max_iterations - total_iterations_ + batch_leftover_);
}
private:
bool started_;
bool finished_;
// When total_iterations_ is 0, KeepRunning() and friends will return false.
size_t total_iterations_;
// May be larger than max_iterations.
std::vector<int> range_;
internal::JSONPointer json_input_;
......@@ -653,6 +660,11 @@ class State {
bool error_occurred_;
// When using KeepRunningBatch(), batch_leftover_ holds the number of
// iterations beyond max_iters that were run. Used to track
// completed_iterations_ accurately.
size_t batch_leftover_;
public:
// Container for user-defined counters.
UserCounters counters;
......@@ -675,6 +687,50 @@ class State {
BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State);
};
inline BENCHMARK_ALWAYS_INLINE
bool State::KeepRunning() {
// total_iterations_ is set to 0 by the constructor, and always set to a
// nonzero value by StartKepRunning().
if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ != 0, true)) {
--total_iterations_;
return true;
}
if (!started_) {
StartKeepRunning();
if (!error_occurred_) {
// max_iterations > 0. The first iteration is always valid.
--total_iterations_;
return true;
}
}
FinishKeepRunning();
return false;
}
inline BENCHMARK_ALWAYS_INLINE
bool State::KeepRunningBatch(size_t n) {
// total_iterations_ is set to 0 by the constructor, and always set to a
// nonzero value by StartKepRunning().
if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
total_iterations_ -= n;
return true;
}
if (!started_) {
StartKeepRunning();
if (!error_occurred_ && total_iterations_ >= n) {
total_iterations_-= n;
return true;
}
}
if (total_iterations_ != 0) {
batch_leftover_ = n - total_iterations_;
total_iterations_ = 0;
return true;
}
FinishKeepRunning();
return false;
}
struct State::StateIterator {
struct BENCHMARK_UNUSED Value {};
typedef std::forward_iterator_tag iterator_category;
......
......@@ -280,7 +280,7 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b,
State st(iters, b->arg, internal::JSONPointer(b->json_arg), thread_id,
b->threads, &timer, manager);
b->benchmark->Run(st);
CHECK(st.iterations() == st.max_iterations)
CHECK(st.iterations() >= st.max_iterations)
<< "Benchmark returned before State::KeepRunning() returned false!";
{
MutexLock l(manager->GetBenchmarkMutex());
......@@ -421,7 +421,7 @@ State::State(size_t max_iters, const std::vector<int>& ranges,
internal::ThreadManager* manager)
: started_(false),
finished_(false),
total_iterations_(max_iters + 1),
total_iterations_(0),
range_(ranges),
json_input_(std::move(json_ptr)),
json_output_(json::object_t{}),
......@@ -429,6 +429,7 @@ State::State(size_t max_iters, const std::vector<int>& ranges,
items_processed_(0),
complexity_n_(0),
error_occurred_(false),
batch_leftover_(0),
counters(),
thread_index(thread_i),
threads(n_threads),
......@@ -436,7 +437,6 @@ State::State(size_t max_iters, const std::vector<int>& ranges,
timer_(timer),
manager_(manager) {
CHECK(max_iterations != 0) << "At least one iteration must be run";
CHECK(total_iterations_ != 0) << "max iterations wrapped around";
CHECK_LT(thread_index, threads) << "thread_index must be less than threads";
}
......@@ -461,7 +461,7 @@ void State::SkipWithError(const char* msg) {
manager_->results.has_error_ = true;
}
}
total_iterations_ = 1;
total_iterations_ = 0;
if (timer_->running()) timer_->StopTimer();
}
......@@ -477,6 +477,7 @@ void State::SetLabel(const char* label) {
void State::StartKeepRunning() {
CHECK(!started_ && !finished_);
started_ = true;
total_iterations_ = error_occurred_ ? 0 : max_iterations;
manager_->StartStopBarrier();
if (!error_occurred_) ResumeTiming();
}
......@@ -486,8 +487,8 @@ void State::FinishKeepRunning() {
if (!error_occurred_) {
PauseTiming();
}
// Total iterations has now wrapped around zero. Fix this.
total_iterations_ = 1;
// Total iterations has now wrapped around past 0. Fix this.
total_iterations_ = 0;
finished_ = true;
manager_->StartStopBarrier();
}
......
......@@ -11,29 +11,35 @@
#endif
#if defined(__clang__)
#define COMPILER_CLANG
#if !defined(COMPILER_CLANG)
#define COMPILER_CLANG
#endif
#elif defined(_MSC_VER)
#define COMPILER_MSVC
#if !defined(COMPILER_MSVC)
#define COMPILER_MSVC
#endif
#elif defined(__GNUC__)
#define COMPILER_GCC
#if !defined(COMPILER_GCC)
#define COMPILER_GCC
#endif
#endif
#if __has_feature(cxx_attributes)
#define BENCHMARK_NORETURN [[noreturn]]
#define BENCHMARK_NORETURN [[noreturn]]
#elif defined(__GNUC__)
#define BENCHMARK_NORETURN __attribute__((noreturn))
#define BENCHMARK_NORETURN __attribute__((noreturn))
#elif defined(COMPILER_MSVC)
#define BENCHMARK_NORETURN __declspec(noreturn)
#define BENCHMARK_NORETURN __declspec(noreturn)
#else
#define BENCHMARK_NORETURN
#define BENCHMARK_NORETURN
#endif
#if defined(__CYGWIN__)
#define BENCHMARK_OS_CYGWIN 1
#define BENCHMARK_OS_CYGWIN 1
#elif defined(_WIN32)
#define BENCHMARK_OS_WINDOWS 1
#define BENCHMARK_OS_WINDOWS 1
#elif defined(__APPLE__)
#include "TargetConditionals.h"
#include "TargetConditionals.h"
#if defined(TARGET_OS_MAC)
#define BENCHMARK_OS_MACOSX 1
#if defined(TARGET_OS_IPHONE)
......@@ -41,36 +47,36 @@
#endif
#endif
#elif defined(__FreeBSD__)
#define BENCHMARK_OS_FREEBSD 1
#define BENCHMARK_OS_FREEBSD 1
#elif defined(__NetBSD__)
#define BENCHMARK_OS_NETBSD 1
#define BENCHMARK_OS_NETBSD 1
#elif defined(__linux__)
#define BENCHMARK_OS_LINUX 1
#define BENCHMARK_OS_LINUX 1
#elif defined(__native_client__)
#define BENCHMARK_OS_NACL 1
#define BENCHMARK_OS_NACL 1
#elif defined(EMSCRIPTEN)
#define BENCHMARK_OS_EMSCRIPTEN 1
#define BENCHMARK_OS_EMSCRIPTEN 1
#elif defined(__rtems__)
#define BENCHMARK_OS_RTEMS 1
#define BENCHMARK_OS_RTEMS 1
#endif
#if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \
&& !defined(__EXCEPTIONS)
#define BENCHMARK_HAS_NO_EXCEPTIONS
#define BENCHMARK_HAS_NO_EXCEPTIONS
#endif
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
#define BENCHMARK_MAYBE_UNUSED __attribute__((unused))
#define BENCHMARK_MAYBE_UNUSED __attribute__((unused))
#else
#define BENCHMARK_MAYBE_UNUSED
#define BENCHMARK_MAYBE_UNUSED
#endif
#if defined(COMPILER_GCC) || __has_builtin(__builtin_unreachable)
#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
#elif defined(COMPILER_MSVC)
#define BENCHMARK_UNREACHABLE() __assume(false)
#define BENCHMARK_UNREACHABLE() __assume(false)
#else
#define BENCHMARK_UNREACHABLE() ((void)0)
#define BENCHMARK_UNREACHABLE() ((void)0)
#endif
#endif // BENCHMARK_INTERNAL_MACROS_H_
......@@ -30,7 +30,7 @@ auto StatisticsSum = [](const std::vector<double>& v) {
};
double StatisticsMean(const std::vector<double>& v) {
if (v.size() == 0) return 0.0;
if (v.empty()) return 0.0;
return StatisticsSum(v) * (1.0 / v.size());
}
......@@ -62,7 +62,7 @@ auto Sqrt = [](const double dat) {
double StatisticsStdDev(const std::vector<double>& v) {
const auto mean = StatisticsMean(v);
if (v.size() == 0) return mean;
if (v.empty()) return mean;
// Sample standard deviation is undefined for n = 1
if (v.size() == 1)
......
......@@ -303,7 +303,7 @@ std::vector<CPUInfo::CacheInfo> GetCacheSizesWindows() {
if (!B.test(0)) continue;
CInfo* Cache = &it->Cache;
CPUInfo::CacheInfo C;
C.num_sharing = B.count();
C.num_sharing = static_cast<int>(B.count());
C.level = Cache->Level;
C.size = Cache->Size;
switch (Cache->Type) {
......
......@@ -102,10 +102,21 @@ void BM_KeepRunning(benchmark::State& state) {
while (state.KeepRunning()) {
++iter_count;
}
assert(iter_count == state.max_iterations);
assert(iter_count == state.iterations());
}
BENCHMARK(BM_KeepRunning);
void BM_KeepRunningBatch(benchmark::State& state) {
// Choose a prime batch size to avoid evenly dividing max_iterations.
const size_t batch_size = 101;
size_t iter_count = 0;
while (state.KeepRunningBatch(batch_size)) {
iter_count += batch_size;
}
assert(state.iterations() == iter_count);
}
BENCHMARK(BM_KeepRunningBatch);
void BM_RangedFor(benchmark::State& state) {
size_t iter_count = 0;
for (auto _ : state) {
......
......@@ -70,6 +70,16 @@ void BM_error_before_running(benchmark::State& state) {
BENCHMARK(BM_error_before_running);
ADD_CASES("BM_error_before_running", {{"", true, "error message"}});
void BM_error_before_running_batch(benchmark::State& state) {
state.SkipWithError("error message");
while (state.KeepRunningBatch(17)) {
assert(false);
}
}
BENCHMARK(BM_error_before_running_batch);
ADD_CASES("BM_error_before_running_batch", {{"", true, "error message"}});
void BM_error_before_running_range_for(benchmark::State& state) {
state.SkipWithError("error message");
for (auto _ : state) {
......
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