Use "auto" with GENERATOR instead of std::function
authorTom Jackson <tjackson@fb.com>
Tue, 28 Nov 2017 01:13:37 +0000 (17:13 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 28 Nov 2017 01:21:54 +0000 (17:21 -0800)
Summary: Now that we're using C++14 more broadly, we should use it to improve generator performance. This speeds up a microbenchmark >5x by removing type erasure.

Reviewed By: philippv

Differential Revision: D6398730

fbshipit-source-id: 5809058a3b5ff0e66fd4b1e8954698944e1a7d09

folly/gen/Base.h
folly/gen/test/BaseBenchmark.cpp

index a550393554a6fa490b633753886b1b417c03ee97..dd74a092a68046adc2e889839034ed82d0cab914 100644 (file)
@@ -503,9 +503,8 @@ Yield generator(Source&& source) {
  *
  *  auto gen = GENERATOR(int) { yield(1); yield(2); };
  */
  *
  *  auto gen = GENERATOR(int) { yield(1); yield(2); };
  */
-#define GENERATOR(TYPE)                            \
-  ::folly::gen::detail::GeneratorBuilder<TYPE>() + \
-   [=](const std::function<void(TYPE)>& yield)
+#define GENERATOR(TYPE) \
+  ::folly::gen::detail::GeneratorBuilder<TYPE>() + [=](auto&& yield)
 
 /*
  * empty() - for producing empty sequences.
 
 /*
  * empty() - for producing empty sequences.
index f11fef0f07bff442fdebf734765f7d75657ffbda..51058b71b960dba0dfba9d59320c127e2d825da6 100644 (file)
@@ -140,11 +140,11 @@ BENCHMARK_DRAW_LINE()
 BENCHMARK(Fib_Sum_NoGen, iters) {
   int s = 0;
   while (iters--) {
 BENCHMARK(Fib_Sum_NoGen, iters) {
   int s = 0;
   while (iters--) {
-    auto fib = [](int limit) -> vector<int> {
+    auto fib = [](size_t limit) -> vector<int> {
       vector<int> ret;
       int a = 0;
       int b = 1;
       vector<int> ret;
       int a = 0;
       int b = 1;
-      for (int i = 0; i * 2 < limit; ++i) {
+      for (size_t i = 0; i < limit; i += 2) {
         ret.push_back(a += b);
         ret.push_back(b += a);
       }
         ret.push_back(a += b);
         ret.push_back(b += a);
       }
@@ -168,11 +168,30 @@ BENCHMARK_RELATIVE(Fib_Sum_Gen, iters) {
         yield(b += a);
       }
     };
         yield(b += a);
       }
     };
+    // Early stopping implemented with exceptions.
     s += fib | take(testSize.load()) | sum;
   }
   folly::doNotOptimizeAway(s);
 }
 
     s += fib | take(testSize.load()) | sum;
   }
   folly::doNotOptimizeAway(s);
 }
 
+BENCHMARK_RELATIVE(Fib_Sum_Gen_Limit, iters) {
+  int s = 0;
+  while (iters--) {
+    size_t limit = testSize.load();
+    auto fib = GENERATOR(int) {
+      int a = 0;
+      int b = 1;
+      for (size_t i = 0; i < limit; i += 2) {
+        yield(a += b);
+        yield(b += a);
+      }
+    };
+    // No early stopping.
+    s += fib | sum;
+  }
+  folly::doNotOptimizeAway(s);
+}
+
 struct FibYielder {
   template <class Yield>
   void operator()(Yield&& yield) const {
 struct FibYielder {
   template <class Yield>
   void operator()(Yield&& yield) const {