/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
DEFINE_bool(benchmark, false, "Run benchmarks.");
DEFINE_bool(json, false, "Output in JSON format.");
-DEFINE_string(bm_regex, "",
- "Only benchmarks whose names match this regex will be run.");
+DEFINE_string(
+ bm_regex,
+ "",
+ "Only benchmarks whose names match this regex will be run.");
-DEFINE_int64(bm_min_usec, 100,
- "Minimum # of microseconds we'll accept for each benchmark.");
+DEFINE_int64(
+ bm_min_usec,
+ 100,
+ "Minimum # of microseconds we'll accept for each benchmark.");
-DEFINE_int64(bm_min_iters, 1,
- "Minimum # of iterations we'll try for each benchmark.");
+DEFINE_int32(
+ bm_min_iters,
+ 1,
+ "Minimum # of iterations we'll try for each benchmark.");
-DEFINE_int32(bm_max_secs, 1,
- "Maximum # of seconds we'll spend on each benchmark.");
+DEFINE_int64(
+ bm_max_iters,
+ 1L << 30L,
+ "Maximum # of iterations we'll try for each benchmark.");
+DEFINE_int32(
+ bm_max_secs,
+ 1,
+ "Maximum # of seconds we'll spend on each benchmark.");
namespace folly {
typedef function<detail::TimeIterPair(unsigned int)> BenchmarkFun;
-vector<tuple<const char*, const char*, BenchmarkFun>>& benchmarks() {
- static vector<tuple<const char*, const char*, BenchmarkFun>> _benchmarks;
+vector<tuple<string, string, BenchmarkFun>>& benchmarks() {
+ static vector<tuple<string, string, BenchmarkFun>> _benchmarks;
return _benchmarks;
}
auto it = std::find_if(
benchmarks().begin(),
benchmarks().end(),
- [global](const tuple<const char*, const char*, BenchmarkFun> &v) {
- return std::strcmp(get<1>(v), global) == 0;
+ [global](const tuple<string, string, BenchmarkFun> &v) {
+ return get<1>(v) == global;
}
);
CHECK(it != benchmarks().end());
// They key here is accuracy; too low numbers means the accuracy was
// coarse. We up the ante until we get to at least minNanoseconds
// timings.
- static uint64_t resolutionInNs = 0, coarseResolutionInNs = 0;
+ static uint64_t resolutionInNs = 0;
if (!resolutionInNs) {
timespec ts;
- CHECK_EQ(0, clock_getres(detail::DEFAULT_CLOCK_ID, &ts));
+ CHECK_EQ(0, clock_getres(CLOCK_REALTIME, &ts));
CHECK_EQ(0, ts.tv_sec) << "Clock sucks.";
CHECK_LT(0, ts.tv_nsec) << "Clock too fast for its own good.";
CHECK_EQ(1, ts.tv_nsec) << "Clock too coarse, upgrade your kernel.";
size_t actualEpochs = 0;
for (; actualEpochs < epochs; ++actualEpochs) {
- for (unsigned int n = FLAGS_bm_min_iters; n < (1UL << 30); n *= 2) {
+ const auto maxIters = FLAGS_bm_max_iters;
+ for (unsigned int n = FLAGS_bm_min_iters; n < maxIters; n *= 2) {
auto const nsecsAndIter = fun(n);
if (nsecsAndIter.first < minNanoseconds) {
continue;
}
static void printBenchmarkResultsAsTable(
- const vector<tuple<const char*, const char*, double> >& data) {
+ const vector<tuple<string, string, double> >& data) {
// Width available
static const unsigned int columns = 76;
// Compute the longest benchmark name
size_t longestName = 0;
FOR_EACH_RANGE (i, 1, benchmarks().size()) {
- longestName = max(longestName, strlen(get<1>(benchmarks()[i])));
+ longestName = max(longestName, get<1>(benchmarks()[i]).size());
}
// Print a horizontal rule
};
// Print header for a file
- auto header = [&](const char* file) {
+ auto header = [&](const string& file) {
separator('=');
printf("%-*srelative time/iter iters/s\n",
- columns - 28, file);
+ columns - 28, file.c_str());
separator('=');
};
double baselineNsPerIter = numeric_limits<double>::max();
- const char* lastFile = "";
+ string lastFile;
for (auto& datum : data) {
auto file = get<0>(datum);
- if (strcmp(file, lastFile)) {
+ if (file != lastFile) {
// New file starting
header(file);
lastFile = file;
s.resize(columns - 29, ' ');
auto nsPerIter = get<2>(datum);
auto secPerIter = nsPerIter / 1E9;
- auto itersPerSec = 1 / secPerIter;
+ auto itersPerSec = (secPerIter == 0)
+ ? std::numeric_limits<double>::infinity()
+ : (1 / secPerIter);
if (!useBaseline) {
// Print without baseline
printf("%*s %9s %7s\n",
}
static void printBenchmarkResultsAsJson(
- const vector<tuple<const char*, const char*, double> >& data) {
+ const vector<tuple<string, string, double> >& data) {
dynamic d = dynamic::object;
for (auto& datum: data) {
d[std::get<1>(datum)] = std::get<2>(datum) * 1000.;
}
static void printBenchmarkResults(
- const vector<tuple<const char*, const char*, double> >& data) {
+ const vector<tuple<string, string, double> >& data) {
if (FLAGS_json) {
printBenchmarkResultsAsJson(data);
void runBenchmarks() {
CHECK(!benchmarks().empty());
- vector<tuple<const char*, const char*, double>> results;
+ vector<tuple<string, string, double>> results;
results.reserve(benchmarks().size() - 1);
std::unique_ptr<boost::regex> bmRegex;
continue;
}
double elapsed = 0.0;
- if (strcmp(get<1>(benchmarks()[i]), "-") != 0) { // skip separators
+ if (get<1>(benchmarks()[i]) != "-") { // skip separators
if (bmRegex && !boost::regex_search(get<1>(benchmarks()[i]), *bmRegex)) {
continue;
}