Rename stdin, etc. in Subprocess to work with MSVC
[folly.git] / folly / Benchmark.cpp
index 6311fd76d536478265deea1cf6707aee6bd557b0..060c4bf4de0b3dbd489fa37cb716ca49c14371ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 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.
@@ -35,18 +35,30 @@ using namespace std;
 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 {
 
@@ -55,8 +67,8 @@ BenchmarkSuspender::NanosecondsSpent BenchmarkSuspender::nsSpent;
 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;
 }
 
@@ -77,8 +89,8 @@ int getGlobalBenchmarkBaselineIndex() {
   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());
@@ -226,10 +238,10 @@ static double runBenchmarkGetNSPerIteration(const BenchmarkFun& fun,
   // 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.";
@@ -255,7 +267,8 @@ static double runBenchmarkGetNSPerIteration(const BenchmarkFun& fun,
   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;
@@ -347,14 +360,14 @@ static string metricReadable(double n, unsigned int decimals) {
 }
 
 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
@@ -363,19 +376,19 @@ static void printBenchmarkResultsAsTable(
   };
 
   // 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;
@@ -397,7 +410,9 @@ static void printBenchmarkResultsAsTable(
     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",
@@ -418,7 +433,7 @@ static void printBenchmarkResultsAsTable(
 }
 
 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.;
@@ -428,7 +443,7 @@ static void printBenchmarkResultsAsJson(
 }
 
 static void printBenchmarkResults(
-  const vector<tuple<const char*, const char*, double> >& data) {
+  const vector<tuple<string, string, double> >& data) {
 
   if (FLAGS_json) {
     printBenchmarkResultsAsJson(data);
@@ -440,7 +455,7 @@ static void printBenchmarkResults(
 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;
@@ -459,7 +474,7 @@ void runBenchmarks() {
       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;
       }