Add more benchmarks for various conversions
authorMarcus Holland-Moritz <mhx@fb.com>
Wed, 22 Jun 2016 00:26:01 +0000 (17:26 -0700)
committerFacebook Github Bot 5 <facebook-github-bot-5-bot@fb.com>
Wed, 22 Jun 2016 00:38:24 +0000 (17:38 -0700)
Summary:
This adds a couple of new benchmarks that will be used as a basis to
check the performance of a series of upcoming changes to folly::to<>.

It exercises both successful and unsuccessful conversion paths for
string-to-anything, int-to-int, int-to-float, float-to-int, and pair-
of-pointers-to-int conversions.

The following table only shows the newly added benchmarks:

  ==============================================================
  folly/test/ConvBenchmark.cpp                time/iter  iters/s
  ==============================================================
  stringToBoolNumClassic                        12.76ns   78.37M
  stringToBoolNumClassicError                    3.19us  313.37K
  stringToBoolStrClassic                        17.92ns   55.79M
  stringToBoolStrClassicError                    3.21us  311.73K
  --------------------------------------------------------------
  stringToFloatNumClassic                       32.96ns   30.34M
  stringToFloatNumClassicError                   2.73us  366.49K
  stringToFloatStrClassic                       37.37ns   26.76M
  stringToFloatStrClassicError                   2.87us  348.81K
  stringToDoubleNumClassic                      31.30ns   31.95M
  stringToDoubleNumClassicError                  2.69us  371.26K
  stringToDoubleStrClassic                      37.67ns   26.54M
  stringToDoubleStrClassicError                  2.87us  348.97K
  --------------------------------------------------------------
  stringToCharSignedClassic                     16.71ns   59.85M
  stringToCharSignedClassicError                 3.87us  258.50K
  stringToCharUnsignedClassic                   15.49ns   64.54M
  stringToCharUnsignedClassicError               2.73us  366.88K
  stringToIntSignedClassic                      21.26ns   47.03M
  stringToIntSignedClassicError                  3.94us  253.82K
  stringToIntUnsignedClassic                    17.93ns   55.79M
  stringToIntUnsignedClassicError                2.72us  367.93K
  stringToLongLongSignedClassic                 34.63ns   28.88M
  stringToLongLongSignedClassicError             3.94us  253.52K
  stringToLongLongUnsignedClassic               51.04ns   19.59M
  stringToLongLongUnsignedClassicError           2.73us  366.58K
  --------------------------------------------------------------
  ptrPairToCharSignedClassic                     5.16ns  193.62M
  ptrPairToCharSignedClassicError                3.56us  280.99K
  ptrPairToCharUnsignedClassic                   2.43ns  411.44M
  ptrPairToCharUnsignedClassicError              2.63us  380.42K
  ptrPairToIntSignedClassic                      6.99ns  143.09M
  ptrPairToIntSignedClassicError                 4.08us  245.27K
  ptrPairToIntUnsignedClassic                    4.25ns  235.09M
  ptrPairToIntUnsignedClassicError               2.70us  370.55K
  ptrPairToLongLongSignedClassic                12.16ns   82.27M
  ptrPairToLongLongSignedClassicError            4.06us  246.17K
  ptrPairToLongLongUnsignedClassic              29.13ns   34.33M
  ptrPairToLongLongUnsignedClassicError          2.71us  369.33K
  --------------------------------------------------------------
  intToCharSignedClassic                       405.02ps    2.47G
  intToCharSignedClassicError                    2.10us  475.11K
  intToCharUnsignedClassic                     303.79ps    3.29G
  intToCharUnsignedClassicError                  2.10us  475.18K
  intToIntSignedClassic                        405.02ps    2.47G
  intToIntSignedClassicError                     1.99us  501.60K
  intToIntUnsignedClassic                      405.03ps    2.47G
  intToIntUnsignedClassicError                   2.09us  478.47K
  --------------------------------------------------------------
  intToFloatClassic                            545.11ps    1.83G
  intToFloatClassicError                         1.67us  599.38K
  --------------------------------------------------------------
  floatToFloatClassic                          759.47ps    1.32G
  floatToFloatClassicError                       6.45us  154.98K
  --------------------------------------------------------------
  floatToIntClassic                            637.82ps    1.57G
  floatToIntClassicError                         1.92us  520.16K
  ==============================================================

Reviewed By: yfeldblum

Differential Revision: D3433745

fbshipit-source-id: 6ab1ede32c07e7fc29b982e8705ecc0138fa6384

folly/test/ConvBenchmark.cpp

index 4a89fa3bdeb921b7a1c94953a263b4c2365f2995..8a805cc46eca02e8bed118cd6c86427f6ba1d979 100644 (file)
@@ -21,6 +21,7 @@
 #include <folly/Benchmark.h>
 #include <folly/Foreach.h>
 
+#include <array>
 #include <limits>
 #include <stdexcept>
 
@@ -382,6 +383,172 @@ DEFINE_BENCHMARK_GROUP(fbstring, 32768);
 
 #undef DEFINE_BENCHMARK_GROUP
 
+namespace {
+
+template <typename T>
+inline void stringToTypeClassic(const char* str, uint32_t n) {
+  for (uint32_t i = 0; i < n; ++i) {
+    try {
+      auto val = to<T>(str);
+      doNotOptimizeAway(val);
+    } catch (const std::exception& e) {
+      doNotOptimizeAway(e.what());
+    }
+    doNotOptimizeAway(i);
+  }
+}
+
+template <typename T>
+inline void ptrPairToIntClassic(StringPiece sp, uint32_t n) {
+  for (uint32_t i = 0; i < n; ++i) {
+    try {
+      auto val = to<T>(sp.begin(), sp.end());
+      doNotOptimizeAway(val);
+    } catch (const std::exception& e) {
+      doNotOptimizeAway(e.what());
+    }
+    doNotOptimizeAway(i);
+  }
+}
+
+constexpr uint32_t kArithNumIter = 10000;
+
+template <typename T, typename U>
+inline size_t arithToArithClassic(const U* in, uint32_t numItems) {
+  for (uint32_t i = 0; i < kArithNumIter; ++i) {
+    for (uint32_t j = 0; j < numItems; ++j) {
+      try {
+        auto val = to<T>(in[j]);
+        doNotOptimizeAway(val);
+      } catch (const std::exception& e) {
+        doNotOptimizeAway(e.what());
+      }
+      doNotOptimizeAway(j);
+    }
+    doNotOptimizeAway(i);
+  }
+
+  return kArithNumIter * numItems;
+}
+
+} // namespace
+
+namespace conv {
+
+std::array<int, 4> int2ScharGood{{-128, 127, 0, -50}};
+std::array<int, 4> int2ScharBad{{-129, 128, 255, 10000}};
+std::array<int, 4> int2UcharGood{{0, 1, 254, 255}};
+std::array<int, 4> int2UcharBad{{-128, -1000, 256, -1}};
+
+std::array<long long, 4> ll2SintOrFloatGood{{-2, -1, 0, 1}};
+std::array<long long, 4> ll2SintOrFloatBad{{
+    std::numeric_limits<long long>::min() / 5,
+    std::numeric_limits<long long>::min() / 2,
+    std::numeric_limits<long long>::max() / 2,
+    std::numeric_limits<long long>::max() / 5,
+}};
+std::array<long long, 4> ll2UintGood{{1, 2, 3, 4}};
+std::array<long long, 4> ll2UintBad{{-1, -2, -3, -4}};
+
+std::array<double, 4> double2FloatGood{{1.0, 1.25, 2.5, 1000.0}};
+std::array<double, 4> double2FloatBad{{1e100, 1e101, 1e102, 1e103}};
+std::array<double, 4> double2IntGood{{1.0, 10.0, 100.0, 1000.0}};
+std::array<double, 4> double2IntBad{{1e100, 1.25, 2.5, 100.00001}};
+}
+
+using namespace conv;
+
+#define STRING_TO_TYPE_BENCHMARK(type, name, pass, fail) \
+  BENCHMARK(stringTo##name##Classic, n) {                \
+    stringToTypeClassic<type>(pass, n);                  \
+  }                                                      \
+  BENCHMARK(stringTo##name##ClassicError, n) {           \
+    stringToTypeClassic<type>(fail, n);                  \
+  }
+
+#define PTR_PAIR_TO_INT_BENCHMARK(type, name, pass, fail) \
+  BENCHMARK(ptrPairTo##name##Classic, n) {                \
+    ptrPairToIntClassic<type>(pass, n);                   \
+  }                                                       \
+  BENCHMARK(ptrPairTo##name##ClassicError, n) {           \
+    ptrPairToIntClassic<type>(fail, n);                   \
+  }
+
+#define ARITH_TO_ARITH_BENCHMARK(type, name, pass, fail)        \
+  BENCHMARK_MULTI(name##Classic) {                              \
+    return arithToArithClassic<type>(pass.data(), pass.size()); \
+  }                                                             \
+  BENCHMARK_MULTI(name##ClassicError) {                         \
+    return arithToArithClassic<type>(fail.data(), fail.size()); \
+  }
+
+#define INT_TO_ARITH_BENCHMARK(type, name, pass, fail) \
+  ARITH_TO_ARITH_BENCHMARK(type, intTo##name, pass, fail)
+
+#define FLOAT_TO_ARITH_BENCHMARK(type, name, pass, fail) \
+  ARITH_TO_ARITH_BENCHMARK(type, floatTo##name, pass, fail)
+
+STRING_TO_TYPE_BENCHMARK(bool, BoolNum, " 1 ", "2")
+STRING_TO_TYPE_BENCHMARK(bool, BoolStr, "true", "xxxx")
+BENCHMARK_DRAW_LINE();
+STRING_TO_TYPE_BENCHMARK(float, FloatNum, " 3.14 ", "3e5000x")
+STRING_TO_TYPE_BENCHMARK(float, FloatStr, "-infinity", "xxxx")
+STRING_TO_TYPE_BENCHMARK(double, DoubleNum, " 3.14 ", "3e5000x")
+STRING_TO_TYPE_BENCHMARK(double, DoubleStr, "-infinity", "xxxx")
+BENCHMARK_DRAW_LINE();
+STRING_TO_TYPE_BENCHMARK(signed char, CharSigned, " -47 ", "1000")
+STRING_TO_TYPE_BENCHMARK(unsigned char, CharUnsigned, " 47 ", "-47")
+STRING_TO_TYPE_BENCHMARK(int, IntSigned, " -4711 ", "-10000000000000000000000")
+STRING_TO_TYPE_BENCHMARK(unsigned int, IntUnsigned, " 4711 ", "-4711")
+STRING_TO_TYPE_BENCHMARK(
+    long long,
+    LongLongSigned,
+    " -8123456789123456789 ",
+    "-10000000000000000000000")
+STRING_TO_TYPE_BENCHMARK(
+    unsigned long long,
+    LongLongUnsigned,
+    " 18123456789123456789 ",
+    "-4711")
+BENCHMARK_DRAW_LINE();
+
+PTR_PAIR_TO_INT_BENCHMARK(signed char, CharSigned, "-47", "1000")
+PTR_PAIR_TO_INT_BENCHMARK(unsigned char, CharUnsigned, "47", "1000")
+PTR_PAIR_TO_INT_BENCHMARK(int, IntSigned, "-4711", "-10000000000000000000000")
+PTR_PAIR_TO_INT_BENCHMARK(
+    unsigned int,
+    IntUnsigned,
+    "4711",
+    "10000000000000000000000")
+PTR_PAIR_TO_INT_BENCHMARK(
+    long long,
+    LongLongSigned,
+    "-8123456789123456789",
+    "-10000000000000000000000")
+PTR_PAIR_TO_INT_BENCHMARK(
+    unsigned long long,
+    LongLongUnsigned,
+    "18123456789123456789",
+    "20000000000000000000")
+BENCHMARK_DRAW_LINE();
+
+INT_TO_ARITH_BENCHMARK(signed char, CharSigned, int2ScharGood, int2ScharBad)
+INT_TO_ARITH_BENCHMARK(unsigned char, CharUnsigned, int2UcharGood, int2UcharBad)
+INT_TO_ARITH_BENCHMARK(int, IntSigned, ll2SintOrFloatGood, ll2SintOrFloatBad)
+INT_TO_ARITH_BENCHMARK(unsigned int, IntUnsigned, ll2UintGood, ll2UintBad)
+BENCHMARK_DRAW_LINE();
+INT_TO_ARITH_BENCHMARK(float, Float, ll2SintOrFloatGood, ll2SintOrFloatBad)
+BENCHMARK_DRAW_LINE();
+FLOAT_TO_ARITH_BENCHMARK(float, Float, double2FloatGood, double2FloatBad)
+BENCHMARK_DRAW_LINE();
+FLOAT_TO_ARITH_BENCHMARK(int, Int, double2IntGood, double2IntBad)
+
+#undef STRING_TO_TYPE_BENCHMARK
+#undef PTR_PAIR_TO_INT_BENCHMARK
+#undef ARITH_TO_ARITH_BENCHMARK
+#undef INT_TO_ARITH_BENCHMARK
+#undef FLOAT_TO_ARITH_BENCHMARK
+
 int main(int argc, char** argv) {
   gflags::ParseCommandLineFlags(&argc, &argv, true);
   folly::runBenchmarks();