Move StringTest benchmarks into StringBenchmark.cpp
authorMichael Lee <mzlee@fb.com>
Wed, 20 Jan 2016 15:10:31 +0000 (07:10 -0800)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Wed, 20 Jan 2016 15:20:30 +0000 (07:20 -0800)
Summary: StringTest.cpp is a mix of benchmarks and normal unittests. Fixing this.

Reviewed By: yfeldblum

Differential Revision: D2840804

fb-gh-sync-id: d3efc357f5f09385e9f69b70e38b64d59045ff0d

folly/test/Makefile.am
folly/test/StringBenchmark.cpp
folly/test/StringTest.cpp

index 7c277e19503aea40fdbc50a2cc0f37027bdb1417..c9dec17318c2832cadc28122b7ac92b097ab6cbe 100644 (file)
@@ -149,7 +149,7 @@ map_util_test_LDADD = libgtestmain.la $(top_builddir)/libfolly.la
 TESTS += map_util_test
 
 string_test_SOURCES = StringTest.cpp
-string_test_LDADD = libgtest.la $(top_builddir)/libfolly.la $(top_builddir)/libfollybenchmark.la
+string_test_LDADD = libgtest.la $(top_builddir)/libfolly.la
 TESTS += string_test
 
 producer_consumer_queue_test_SOURCES = ProducerConsumerQueueTest.cpp
index c9c90d7dbee70892074359764e52dcf58d25f12f..dfcd47eb907286964e14bcc2008f8f1b3415045c 100644 (file)
  * limitations under the License.
  */
 
-#include <folly/Benchmark.h>
 #include <folly/String.h>
 
+#include <boost/algorithm/string.hpp>
+#include <cstdarg>
+#include <folly/Benchmark.h>
+#include <random>
+
+using namespace folly;
+using namespace std;
+
 BENCHMARK(libc_tolower, iters) {
   static const size_t kSize = 256;
   // This array is static to keep the compiler from optimizing the
@@ -47,12 +54,210 @@ BENCHMARK(folly_toLowerAscii, iters) {
   }
 }
 
+// A simple benchmark that tests various output sizes for a simple
+// input; the goal is to measure the output buffer resize code cost.
+void stringPrintfOutputSize(int iters, int param) {
+  string buffer;
+  BENCHMARK_SUSPEND { buffer.resize(param, 'x'); }
+
+  for (int64_t i = 0; i < iters; ++i) {
+    string s = stringPrintf("msg: %d, %d, %s", 10, 20, buffer.c_str());
+  }
+}
+
+// The first few of these tend to fit in the inline buffer, while the
+// subsequent ones cross that limit, trigger a second vsnprintf, and
+// exercise a different codepath.
+BENCHMARK_PARAM(stringPrintfOutputSize, 1)
+BENCHMARK_PARAM(stringPrintfOutputSize, 4)
+BENCHMARK_PARAM(stringPrintfOutputSize, 16)
+BENCHMARK_PARAM(stringPrintfOutputSize, 64)
+BENCHMARK_PARAM(stringPrintfOutputSize, 256)
+BENCHMARK_PARAM(stringPrintfOutputSize, 1024)
+
+// Benchmark simple stringAppendf behavior to show a pathology Lovro
+// reported (t5735468).
+BENCHMARK(stringPrintfAppendfBenchmark, iters) {
+  for (unsigned int i = 0; i < iters; ++i) {
+    string s;
+    BENCHMARK_SUSPEND { s.reserve(300000); }
+    for (int j = 0; j < 300000; ++j) {
+      stringAppendf(&s, "%d", 1);
+    }
+  }
+}
+
+namespace {
+fbstring cbmString;
+fbstring cbmEscapedString;
+fbstring cEscapedString;
+fbstring cUnescapedString;
+const size_t kCBmStringLength = 64 << 10;
+const uint32_t kCPrintablePercentage = 90;
+
+fbstring uribmString;
+fbstring uribmEscapedString;
+fbstring uriEscapedString;
+fbstring uriUnescapedString;
+const size_t kURIBmStringLength = 256;
+const uint32_t kURIPassThroughPercentage = 50;
+
+void initBenchmark() {
+  std::mt19937 rnd;
+
+  // C escape
+  std::uniform_int_distribution<uint32_t> printable(32, 126);
+  std::uniform_int_distribution<uint32_t> nonPrintable(0, 160);
+  std::uniform_int_distribution<uint32_t> percentage(0, 99);
+
+  cbmString.reserve(kCBmStringLength);
+  for (size_t i = 0; i < kCBmStringLength; ++i) {
+    unsigned char c;
+    if (percentage(rnd) < kCPrintablePercentage) {
+      c = printable(rnd);
+    } else {
+      c = nonPrintable(rnd);
+      // Generate characters in both non-printable ranges:
+      // 0..31 and 127..255
+      if (c >= 32) {
+        c += (126 - 32) + 1;
+      }
+    }
+    cbmString.push_back(c);
+  }
+
+  cbmEscapedString = cEscape<fbstring>(cbmString);
+
+  // URI escape
+  std::uniform_int_distribution<uint32_t> passthrough('a', 'z');
+  std::string encodeChars = " ?!\"',+[]";
+  std::uniform_int_distribution<uint32_t> encode(0, encodeChars.size() - 1);
+
+  uribmString.reserve(kURIBmStringLength);
+  for (size_t i = 0; i < kURIBmStringLength; ++i) {
+    unsigned char c;
+    if (percentage(rnd) < kURIPassThroughPercentage) {
+      c = passthrough(rnd);
+    } else {
+      c = encodeChars[encode(rnd)];
+    }
+    uribmString.push_back(c);
+  }
+
+  uribmEscapedString = uriEscape<fbstring>(uribmString);
+}
+
+BENCHMARK(BM_cEscape, iters) {
+  while (iters--) {
+    cEscapedString = cEscape<fbstring>(cbmString);
+    doNotOptimizeAway(cEscapedString.size());
+  }
+}
+
+BENCHMARK(BM_cUnescape, iters) {
+  while (iters--) {
+    cUnescapedString = cUnescape<fbstring>(cbmEscapedString);
+    doNotOptimizeAway(cUnescapedString.size());
+  }
+}
+
+BENCHMARK(BM_uriEscape, iters) {
+  while (iters--) {
+    uriEscapedString = uriEscape<fbstring>(uribmString);
+    doNotOptimizeAway(uriEscapedString.size());
+  }
+}
+
+BENCHMARK(BM_uriUnescape, iters) {
+  while (iters--) {
+    uriUnescapedString = uriUnescape<fbstring>(uribmEscapedString);
+    doNotOptimizeAway(uriUnescapedString.size());
+  }
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////////////////
+
+BENCHMARK(splitOnSingleChar, iters) {
+  static const std::string line = "one:two:three:four";
+  for (size_t i = 0; i < iters << 4; ++i) {
+    std::vector<StringPiece> pieces;
+    folly::split(':', line, pieces);
+  }
+}
+
+BENCHMARK(splitOnSingleCharFixed, iters) {
+  static const std::string line = "one:two:three:four";
+  for (size_t i = 0; i < iters << 4; ++i) {
+    StringPiece a, b, c, d;
+    folly::split(':', line, a, b, c, d);
+  }
+}
+
+BENCHMARK(splitOnSingleCharFixedAllowExtra, iters) {
+  static const std::string line = "one:two:three:four";
+  for (size_t i = 0; i < iters << 4; ++i) {
+    StringPiece a, b, c, d;
+    folly::split<false>(':', line, a, b, c, d);
+  }
+}
+
+BENCHMARK(splitStr, iters) {
+  static const std::string line = "one-*-two-*-three-*-four";
+  for (size_t i = 0; i < iters << 4; ++i) {
+    std::vector<StringPiece> pieces;
+    folly::split("-*-", line, pieces);
+  }
+}
+
+BENCHMARK(splitStrFixed, iters) {
+  static const std::string line = "one-*-two-*-three-*-four";
+  for (size_t i = 0; i < iters << 4; ++i) {
+    StringPiece a, b, c, d;
+    folly::split("-*-", line, a, b, c, d);
+  }
+}
+
+BENCHMARK(boost_splitOnSingleChar, iters) {
+  static const std::string line = "one:two:three:four";
+  bool (*pred)(char) = [](char c) -> bool { return c == ':'; };
+  for (size_t i = 0; i < iters << 4; ++i) {
+    std::vector<boost::iterator_range<std::string::const_iterator>> pieces;
+    boost::split(pieces, line, pred);
+  }
+}
+
+BENCHMARK(joinCharStr, iters) {
+  static const std::vector<std::string> input = {
+      "one", "two", "three", "four", "five", "six", "seven"};
+  for (size_t i = 0; i < iters << 4; ++i) {
+    std::string output;
+    folly::join(':', input, output);
+  }
+}
+
+BENCHMARK(joinStrStr, iters) {
+  static const std::vector<std::string> input = {
+      "one", "two", "three", "four", "five", "six", "seven"};
+  for (size_t i = 0; i < iters << 4; ++i) {
+    std::string output;
+    folly::join(":", input, output);
+  }
+}
+
+BENCHMARK(joinInt, iters) {
+  static const auto input = {123, 456, 78910, 1112, 1314, 151, 61718};
+  for (size_t i = 0; i < iters << 4; ++i) {
+    std::string output;
+    folly::join(":", input, output);
+  }
+}
+
 int main(int argc, char** argv) {
   gflags::ParseCommandLineFlags(&argc, &argv, true);
+  initBenchmark();
   folly::runBenchmarks();
-  if (FLAGS_benchmark) {
-    folly::runBenchmarks();
-  }
   return 0;
 }
 
@@ -61,7 +266,27 @@ Results on x86_64:
 ============================================================================
 folly/test/StringBenchmark.cpp                  relative  time/iter  iters/s
 ============================================================================
-libc_tolower                                                 1.30us  767.50K
-folly_toLowerAscii                                         115.21ns    8.68M
+libc_tolower                                               773.30ns    1.29M
+folly_toLowerAscii                                          65.04ns   15.38M
+stringPrintfOutputSize(1)                                  224.67ns    4.45M
+stringPrintfOutputSize(4)                                  231.53ns    4.32M
+stringPrintfOutputSize(16)                                 286.54ns    3.49M
+stringPrintfOutputSize(64)                                 305.47ns    3.27M
+stringPrintfOutputSize(256)                                  1.48us  674.45K
+stringPrintfOutputSize(1024)                                 5.89us  169.72K
+stringPrintfAppendfBenchmark                                34.43ms    29.04
+BM_cEscape                                                 461.51us    2.17K
+BM_cUnescape                                               328.19us    3.05K
+BM_uriEscape                                                 4.36us  229.25K
+BM_uriUnescape                                               2.22us  450.64K
+splitOnSingleChar                                            1.46us  687.21K
+splitOnSingleCharFixed                                     133.02ns    7.52M
+splitOnSingleCharFixedAllowExtra                            74.35ns   13.45M
+splitStr                                                     2.36us  424.00K
+splitStrFixed                                              282.38ns    3.54M
+boost_splitOnSingleChar                                      2.83us  353.12K
+joinCharStr                                                  2.65us  376.93K
+joinStrStr                                                   2.64us  378.09K
+joinInt                                                      3.89us  257.37K
 ============================================================================
 */
index 526afeecbe129bb3dd0f161733cf1aaf59ace56d..759c4477a907a954252fabbd55d84b121165d1e1 100644 (file)
 
 #include <folly/String.h>
 
-#include <cstdarg>
-#include <random>
-#include <boost/algorithm/string.hpp>
 #include <gtest/gtest.h>
 
-#include <folly/Benchmark.h>
-
 using namespace folly;
 using namespace std;
 
@@ -155,39 +150,6 @@ TEST(StringPrintf, oldStringAppendf) {
   EXPECT_EQ(string("helloa/b/c/d"), s);
 }
 
-// A simple benchmark that tests various output sizes for a simple
-// input; the goal is to measure the output buffer resize code cost.
-void stringPrintfOutputSize(int iters, int param) {
-  string buffer;
-  BENCHMARK_SUSPEND { buffer.resize(param, 'x'); }
-
-  for (int64_t i = 0; i < iters; ++i) {
-    string s = stringPrintf("msg: %d, %d, %s", 10, 20, buffer.c_str());
-  }
-}
-
-// The first few of these tend to fit in the inline buffer, while the
-// subsequent ones cross that limit, trigger a second vsnprintf, and
-// exercise a different codepath.
-BENCHMARK_PARAM(stringPrintfOutputSize, 1)
-BENCHMARK_PARAM(stringPrintfOutputSize, 4)
-BENCHMARK_PARAM(stringPrintfOutputSize, 16)
-BENCHMARK_PARAM(stringPrintfOutputSize, 64)
-BENCHMARK_PARAM(stringPrintfOutputSize, 256)
-BENCHMARK_PARAM(stringPrintfOutputSize, 1024)
-
-// Benchmark simple stringAppendf behavior to show a pathology Lovro
-// reported (t5735468).
-BENCHMARK(stringPrintfAppendfBenchmark, iters) {
-  for (unsigned int i = 0; i < iters; ++i) {
-    string s;
-    BENCHMARK_SUSPEND { s.reserve(300000); }
-    for (int j = 0; j < 300000; ++j) {
-      stringAppendf(&s, "%d", 1);
-    }
-  }
-}
-
 TEST(Escape, cEscape) {
   EXPECT_EQ("hello world", cEscape<std::string>("hello world"));
   EXPECT_EQ("hello \\\\world\\\" goodbye",
@@ -303,96 +265,6 @@ TEST(Escape, uriUnescapePercentDecoding) {
   }
 }
 
-namespace {
-fbstring cbmString;
-fbstring cbmEscapedString;
-fbstring cEscapedString;
-fbstring cUnescapedString;
-const size_t kCBmStringLength = 64 << 10;
-const uint32_t kCPrintablePercentage = 90;
-
-fbstring uribmString;
-fbstring uribmEscapedString;
-fbstring uriEscapedString;
-fbstring uriUnescapedString;
-const size_t kURIBmStringLength = 256;
-const uint32_t kURIPassThroughPercentage = 50;
-
-void initBenchmark() {
-  std::mt19937 rnd;
-
-  // C escape
-  std::uniform_int_distribution<uint32_t> printable(32, 126);
-  std::uniform_int_distribution<uint32_t> nonPrintable(0, 160);
-  std::uniform_int_distribution<uint32_t> percentage(0, 99);
-
-  cbmString.reserve(kCBmStringLength);
-  for (size_t i = 0; i < kCBmStringLength; ++i) {
-    unsigned char c;
-    if (percentage(rnd) < kCPrintablePercentage) {
-      c = printable(rnd);
-    } else {
-      c = nonPrintable(rnd);
-      // Generate characters in both non-printable ranges:
-      // 0..31 and 127..255
-      if (c >= 32) {
-        c += (126 - 32) + 1;
-      }
-    }
-    cbmString.push_back(c);
-  }
-
-  cbmEscapedString = cEscape<fbstring>(cbmString);
-
-  // URI escape
-  std::uniform_int_distribution<uint32_t> passthrough('a', 'z');
-  std::string encodeChars = " ?!\"',+[]";
-  std::uniform_int_distribution<uint32_t> encode(0, encodeChars.size() - 1);
-
-  uribmString.reserve(kURIBmStringLength);
-  for (size_t i = 0; i < kURIBmStringLength; ++i) {
-    unsigned char c;
-    if (percentage(rnd) < kURIPassThroughPercentage) {
-      c = passthrough(rnd);
-    } else {
-      c = encodeChars[encode(rnd)];
-    }
-    uribmString.push_back(c);
-  }
-
-  uribmEscapedString = uriEscape<fbstring>(uribmString);
-}
-
-BENCHMARK(BM_cEscape, iters) {
-  while (iters--) {
-    cEscapedString = cEscape<fbstring>(cbmString);
-    doNotOptimizeAway(cEscapedString.size());
-  }
-}
-
-BENCHMARK(BM_cUnescape, iters) {
-  while (iters--) {
-    cUnescapedString = cUnescape<fbstring>(cbmEscapedString);
-    doNotOptimizeAway(cUnescapedString.size());
-  }
-}
-
-BENCHMARK(BM_uriEscape, iters) {
-  while (iters--) {
-    uriEscapedString = uriEscape<fbstring>(uribmString);
-    doNotOptimizeAway(uriEscapedString.size());
-  }
-}
-
-BENCHMARK(BM_uriUnescape, iters) {
-  while (iters--) {
-    uriUnescapedString = uriUnescape<fbstring>(uribmEscapedString);
-    doNotOptimizeAway(uriUnescapedString.size());
-  }
-}
-
-}  // namespace
-
 namespace {
 
 double pow2(int exponent) {
@@ -1212,84 +1084,6 @@ TEST(String, toLowerAsciiUnaligned) {
   }
 }
 
-//////////////////////////////////////////////////////////////////////
-
-BENCHMARK(splitOnSingleChar, iters) {
-  static const std::string line = "one:two:three:four";
-  for (size_t i = 0; i < iters << 4; ++i) {
-    std::vector<StringPiece> pieces;
-    folly::split(':', line, pieces);
-  }
-}
-
-BENCHMARK(splitOnSingleCharFixed, iters) {
-  static const std::string line = "one:two:three:four";
-  for (size_t i = 0; i < iters << 4; ++i) {
-    StringPiece a, b, c, d;
-    folly::split(':', line, a, b, c, d);
-  }
-}
-
-BENCHMARK(splitOnSingleCharFixedAllowExtra, iters) {
-  static const std::string line = "one:two:three:four";
-  for (size_t i = 0; i < iters << 4; ++i) {
-    StringPiece a, b, c, d;
-    folly::split<false>(':', line, a, b, c, d);
-  }
-}
-
-BENCHMARK(splitStr, iters) {
-  static const std::string line = "one-*-two-*-three-*-four";
-  for (size_t i = 0; i < iters << 4; ++i) {
-    std::vector<StringPiece> pieces;
-    folly::split("-*-", line, pieces);
-  }
-}
-
-BENCHMARK(splitStrFixed, iters) {
-  static const std::string line = "one-*-two-*-three-*-four";
-  for (size_t i = 0; i < iters << 4; ++i) {
-    StringPiece a, b, c, d;
-    folly::split("-*-", line, a, b, c, d);
-  }
-}
-
-BENCHMARK(boost_splitOnSingleChar, iters) {
-  static const std::string line = "one:two:three:four";
-  bool(*pred)(char) = [] (char c) -> bool { return c == ':'; };
-  for (size_t i = 0; i < iters << 4; ++i) {
-    std::vector<boost::iterator_range<std::string::const_iterator> > pieces;
-    boost::split(pieces, line, pred);
-  }
-}
-
-BENCHMARK(joinCharStr, iters) {
-  static const std::vector<std::string> input = {
-    "one", "two", "three", "four", "five", "six", "seven" };
-  for (size_t i = 0; i < iters << 4; ++i) {
-    std::string output;
-    folly::join(':', input, output);
-  }
-}
-
-BENCHMARK(joinStrStr, iters) {
-  static const std::vector<std::string> input = {
-    "one", "two", "three", "four", "five", "six", "seven" };
-  for (size_t i = 0; i < iters << 4; ++i) {
-    std::string output;
-    folly::join(":", input, output);
-  }
-}
-
-BENCHMARK(joinInt, iters) {
-  static const auto input = {
-    123, 456, 78910, 1112, 1314, 151, 61718 };
-  for (size_t i = 0; i < iters << 4; ++i) {
-    std::string output;
-    folly::join(":", input, output);
-  }
-}
-
 TEST(String, whitespace) {
   // trimWhitespace:
   EXPECT_EQ("kavabanga",
@@ -1359,16 +1153,3 @@ TEST(UTF8StringPiece, empty_mid_codepoint) {
 TEST(UTF8StringPiece, invalid_mid_codepoint) {
   EXPECT_THROW(UTF8StringPiece(kTestUTF8.subpiece(9, 1)), std::out_of_range);
 }
-
-int main(int argc, char *argv[]) {
-  testing::InitGoogleTest(&argc, argv);
-  gflags::ParseCommandLineFlags(&argc, &argv, true);
-  auto ret = RUN_ALL_TESTS();
-  if (!ret) {
-    initBenchmark();
-    if (FLAGS_benchmark) {
-      folly::runBenchmarks();
-    }
-  }
-  return ret;
-}