2 * Copyright 2014 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <glog/logging.h>
23 #include <folly/gen/Base.h>
24 #include <folly/gen/Parallel.h>
25 #include <folly/gen/test/Bench.h>
29 std::max(1, (int32_t) sysconf(_SC_NPROCESSORS_CONF) / 2),
32 using namespace folly::gen;
36 constexpr int kFib = 28; // unit of work
37 size_t fib(int n) { return n <= 1 ? 1 : fib(n - 1) + fib(n - 2); }
39 static auto add = [](int a, int b) { return a + b; };
40 static auto mod7 = [](int i) { return i % 7; };
42 static auto isPrimeSlow = [](int n) {
46 for (int d = 3; d * d <= n; d += 2) {
56 seq(1, 1 << 20) | filter(isPrimeSlow) | as<vector>();
58 static auto isPrime = [](int n) {
60 | until([&](int d) { return d * d > n; })
61 | filter([&](int d) { return 0 == n % d; })
65 static auto factors = [](int n) {
67 | until([&](int d) { return d * d > n; })
68 | filter([&](int d) { return 0 == n % d; })
72 static auto factorsSlow = [](int n) {
74 | filter([&](int d) { return 0 == n % d; })
78 static auto sleepyWork = [](int i) {
79 const auto sleepyTime = std::chrono::microseconds(100);
80 std::this_thread::sleep_for(sleepyTime);
84 static auto sleepAndWork = [](int i) {
85 return factorsSlow(i) + sleepyWork(i);
89 static auto workAndBlock = [](int i) {
90 int r = factorsSlow(i);
92 std::lock_guard<std::mutex> lock(block);
93 return sleepyWork(i) + r;
98 auto v = seq(start) | take(1 << 20) | as<vector>();
99 auto small = from(v) | take(1 << 12);
100 auto medium = from(v) | take(1 << 14);
101 auto large = from(v) | take(1 << 18);
103 auto chunks = chunked(v);
105 BENCH_GEN(small | map(factorsSlow) | sum);
106 BENCH_GEN_REL(small | parallel(map(factorsSlow)) | sum);
107 BENCHMARK_DRAW_LINE();
109 BENCH_GEN(small | map(factors) | sum);
110 BENCH_GEN_REL(small | parallel(map(factors)) | sum);
111 BENCHMARK_DRAW_LINE();
113 BENCH_GEN(large | map(factors) | sum);
114 BENCH_GEN_REL(large | parallel(map(factors)) | sum);
115 BENCHMARK_DRAW_LINE();
119 BENCH_GEN(huge | filter(isPrime) | count);
120 BENCH_GEN_REL(ch | cat | filter(isPrime) | count);
121 BENCH_GEN_REL(ch | parallel(cat | filter(isPrime)) | count);
122 BENCH_GEN_REL(ch | parallel(cat | filter(isPrime) | sub(count)) | sum);
123 BENCHMARK_DRAW_LINE();
125 BENCH_GEN(small | map(sleepAndWork) | sum);
126 BENCH_GEN_REL(small | parallel(map(sleepAndWork)) | sum);
127 BENCHMARK_DRAW_LINE();
129 const int fibs = 1000;
130 BENCH_GEN(seq(1, fibs) | map([](int) { return fib(kFib); }) | sum);
131 BENCH_GEN_REL(seq(1, fibs) |
132 parallel(map([](int) { return fib(kFib); }) | sub(sum)) | sum);
134 auto threads = seq(1, int(FLAGS_threads))
136 return std::thread([=] {
137 return range((i + 0) * fibs / FLAGS_threads,
138 (i + 1) * fibs / FLAGS_threads) |
139 map([](int) { return fib(kFib); }) | sum;
143 from(threads) | [](std::thread &thread) { thread.join(); };
146 BENCHMARK_DRAW_LINE();
149 ============================================================================
150 folly/gen/test/ParallelBenchmark.cpp relative time/iter iters/s
151 ============================================================================
152 small | map(factorsSlow) | sum 4.59s 217.87m
153 small | parallel(map(factorsSlow)) | sum 1588.86% 288.88ms 3.46
154 ----------------------------------------------------------------------------
155 small | map(factors) | sum 9.62ms 103.94
156 small | parallel(map(factors)) | sum 89.15% 10.79ms 92.66
157 ----------------------------------------------------------------------------
158 large | map(factors) | sum 650.52ms 1.54
159 large | parallel(map(factors)) | sum 53.82% 1.21s 827.41m
160 ----------------------------------------------------------------------------
161 huge | filter(isPrime) | count 295.93ms 3.38
162 ch | cat | filter(isPrime) | count 99.76% 296.64ms 3.37
163 ch | parallel(cat | filter(isPrime)) | count 142.75% 207.31ms 4.82
164 ch | parallel(cat | filter(isPrime) | sub(count 1538.50% 19.24ms 51.99
165 ----------------------------------------------------------------------------
166 small | map(sleepAndWork) | sum 5.37s 186.18m
167 small | parallel(map(sleepAndWork)) | sum 1840.38% 291.85ms 3.43
168 ----------------------------------------------------------------------------
169 seq(1, fibs) | map([](int) { return fib(kFib); 1.49s 669.53m
170 seq(1, fibs) | parallel(map([](int) { return fi 1698.07% 87.96ms 11.37
171 [] { auto threads = seq(1, int(FLAGS_threads)) 1571.16% 95.06ms 10.52
172 ----------------------------------------------------------------------------
173 ============================================================================
175 int main(int argc, char *argv[]) {
176 google::ParseCommandLineFlags(&argc, &argv, true);
177 folly::runBenchmarks();