benchmark_min_time now works as expected
diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h
index d5dec23..a34f8e6 100644
--- a/include/benchmark/benchmark.h
+++ b/include/benchmark/benchmark.h
@@ -233,7 +233,6 @@
bool MaybeStop();
void NewInterval();
bool AllStarting();
- bool RunAnotherInterval() const;
void Run();
diff --git a/src/benchmark.cc b/src/benchmark.cc
index 0d93eb1..a43a56e 100644
--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -29,11 +29,9 @@
"If this flag is the string \"all\", all benchmarks linked "
"into the process are run.");
-DEFINE_int32(benchmark_min_iters, 100,
- "Minimum number of iterations per benchmark");
-
-DEFINE_int32(benchmark_max_iters, 1000000000,
- "Maximum number of iterations per benchmark");
+DEFINE_int32(benchmark_iterations, 0,
+ "Total number of iterations per benchmark. 0 means the benchmarks "
+ "are time-based.");
DEFINE_double(benchmark_min_time, 0.5,
"Minimum number of seconds we should run benchmark before "
@@ -69,15 +67,13 @@
: NULL )
namespace benchmark {
-
namespace {
-
// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
-static const char kBigSIUnits[] = "kMGTPEZY";
+const char kBigSIUnits[] = "kMGTPEZY";
// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
-static const char kBigIECUnits[] = "KMGTPEZY";
+const char kBigIECUnits[] = "KMGTPEZY";
// milli, micro, nano, pico, femto, atto, zepto, yocto.
-static const char kSmallSIUnits[] = "munpfazy";
+const char kSmallSIUnits[] = "munpfazy";
// We require that all three arrays have the same size.
static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits),
@@ -427,9 +423,8 @@
void PrintUsageAndExit() {
fprintf(stdout, "benchmark [--benchmark_filter=<regex>]\n"
-// TODO " [--benchmark_min_iters=<min_iters>]\n"
-// TODO " [--benchmark_max_iters=<max_iters>]\n"
-// TODO " [--benchmark_min_time=<min_time>]\n"
+// TODO " [--benchmark_iterations=<iterations>]\n"
+ " [--benchmark_min_time=<min_time>]\n"
// " [--benchmark_memory_usage]\n"
// TODO " [--benchmark_repetitions=<num_repetitions>]\n"
" [--color_print={true|false}]\n"
@@ -441,16 +436,16 @@
for (int i = 1; i < *argc; ++i) {
if (ParseStringFlag(argv[i], "benchmark_filter",
&FLAGS_benchmark_filter) ||
- /* TODO(dominic)
- ParseInt32Flag(argv[i], "benchmark_min_iters",
- &FLAGS_benchmark_min_iters) ||
- ParseInt32Flag(argv[i], "benchmark_max_iters",
- &FLAGS_benchmark_max_iters) ||
+ /* TODO
+ ParseInt32Flag(argv[i], "benchmark_iterations",
+ &FLAGS_benchmark_iterations) ||
+ */
ParseDoubleFlag(argv[i], "benchmark_min_time",
&FLAGS_benchmark_min_time) ||
// TODO(dominic)
// ParseBoolFlag(argv[i], "gbenchmark_memory_usage",
// &FLAGS_gbenchmark_memory_usage) ||
+ /*
ParseInt32Flag(argv[i], "benchmark_repetitions",
&FLAGS_benchmark_repetitions) ||
*/
@@ -504,7 +499,7 @@
t = MyCPUUsage() + ChildrenCPUUsage();
break;
}
- return static_cast<int64_t>(t * 1e6);
+ return static_cast<int64_t>(t * kNumMicrosPerSecond);
}
// Reinitialize if necessary (since clock type may be change once benchmark
@@ -577,6 +572,10 @@
SharedState(const internal::Benchmark::Instance* b, int t)
: instance(b), starting(0), stopping(0), threads(t) {
+ pthread_mutex_init(&mu, nullptr);
+ }
+ ~SharedState() {
+ pthread_mutex_destroy(&mu);
}
DISALLOW_COPY_AND_ASSIGN(SharedState);
};
@@ -907,13 +906,17 @@
pause_time_(0.0),
total_iterations_(0),
interval_micros_(
- static_cast<int64_t>(1e6 * FLAGS_benchmark_min_time /
+ static_cast<int64_t>(kNumMicrosPerSecond * FLAGS_benchmark_min_time /
FLAGS_benchmark_repetitions)) {
+ CHECK(clock != nullptr);
+ CHECK(s != nullptr);
}
bool State::KeepRunning() {
// Fast path
- if (!clock_->HasReached(stop_time_micros_ + pause_time_)) {
+ if ((FLAGS_benchmark_iterations == 0 &&
+ !clock_->HasReached(stop_time_micros_ + pause_time_)) ||
+ iterations_ < FLAGS_benchmark_iterations) {
++iterations_;
return true;
}
@@ -1029,12 +1032,12 @@
}
bool State::FinishInterval() {
- if (iterations_ < FLAGS_benchmark_min_iters / FLAGS_benchmark_repetitions &&
- interval_micros_ < 5000000) {
+ if (FLAGS_benchmark_iterations != 0 &&
+ iterations_ < FLAGS_benchmark_iterations / FLAGS_benchmark_repetitions) {
interval_micros_ *= 2;
#ifdef DEBUG
- std::cout << "Interval was too short; trying again for "
- << interval_micros_ << " useconds.\n";
+ std::cout << "Not enough iterations in interval; "
+ << "Trying again for " << interval_micros_ << " useconds.\n";
#endif
is_continuation_ = false;
NewInterval();
@@ -1058,11 +1061,25 @@
bool keep_going = false;
{
mutex_lock l(&shared_->mu);
+
+ // Either replace the last or add a new data point.
if (is_continuation_)
shared_->runs.back() = data;
else
shared_->runs.push_back(data);
- keep_going = RunAnotherInterval();
+
+ if (FLAGS_benchmark_iterations != 0) {
+ // If we need more iterations, run another interval as a continuation.
+ keep_going = total_iterations_ < FLAGS_benchmark_iterations;
+ is_continuation_ = keep_going;
+ } else {
+ // If this is a repetition, run another interval as a new data point.
+ keep_going =
+ shared_->runs.size() <
+ static_cast<size_t>(FLAGS_benchmark_repetitions);
+ is_continuation_ = !keep_going;
+ }
+
if (!keep_going) {
++shared_->stopping;
if (shared_->stopping < shared_->threads) {
@@ -1076,23 +1093,11 @@
}
}
- if (state_ == STATE_RUNNING) {
- is_continuation_ = true;
+ if (state_ == STATE_RUNNING)
NewInterval();
- }
return keep_going;
}
-bool State::RunAnotherInterval() const {
- if (total_iterations_ < FLAGS_benchmark_min_iters)
- return true;
- if (total_iterations_ > FLAGS_benchmark_max_iters)
- return false;
- if (static_cast<int>(shared_->runs.size()) >= FLAGS_benchmark_repetitions)
- return false;
- return true;
-}
-
bool State::MaybeStop() {
mutex_lock l(&shared_->mu);
if (shared_->stopping < shared_->threads) {
diff --git a/src/sleep.cc b/src/sleep.cc
index f1bdf1f..27ce2cf 100644
--- a/src/sleep.cc
+++ b/src/sleep.cc
@@ -5,22 +5,14 @@
namespace benchmark {
#ifdef OS_WINDOWS
-
// Window's _sleep takes milliseconds argument.
void SleepForMilliseconds(int milliseconds) {
_sleep(milliseconds);
}
void SleepForSeconds(double seconds) {
- SleepForMilliseconds(static_cast<int>(seconds * 1000));
+ SleepForMilliseconds(static_cast<int>(kNumMillisPerSecond * seconds));
}
-
#else // OS_WINDOWS
-
-static const int64_t kNumMillisPerSecond = 1000LL;
-static const int64_t kNumMicrosPerMilli = 1000LL;
-static const int64_t kNumMicrosPerSecond = kNumMillisPerSecond * 1000LL;
-static const int64_t kNumNanosPerMicro = 1000LL;
-
void SleepForMicroseconds(int64_t microseconds) {
struct timespec sleep_time;
sleep_time.tv_sec = microseconds / kNumMicrosPerSecond;
@@ -36,7 +28,6 @@
void SleepForSeconds(double seconds) {
SleepForMicroseconds(static_cast<int64_t>(seconds * kNumMicrosPerSecond));
}
-
#endif // OS_WINDOWS
} // end namespace benchmark
diff --git a/src/sleep.h b/src/sleep.h
index 1b60a45..437b5c7 100644
--- a/src/sleep.h
+++ b/src/sleep.h
@@ -4,6 +4,11 @@
#include <stdint.h>
namespace benchmark {
+const int64_t kNumMillisPerSecond = 1000LL;
+const int64_t kNumMicrosPerMilli = 1000LL;
+const int64_t kNumMicrosPerSecond = kNumMillisPerSecond * 1000LL;
+const int64_t kNumNanosPerMicro = 1000LL;
+
void SleepForMicroseconds(int64_t microseconds);
void SleepForMilliseconds(int milliseconds);
void SleepForSeconds(double seconds);