2 * Copyright 2012 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 "folly/experimental/Gen.h"
18 #include "folly/experimental/StringGen.h"
19 #include "folly/experimental/FileGen.h"
24 #include <glog/logging.h>
26 #include "folly/Benchmark.h"
28 using namespace folly;
29 using namespace folly::gen;
36 static std::atomic<int> testSize(1000);
37 static vector<int> testVector =
38 seq(1, testSize.load())
39 | mapped([](int) { return rand(); })
41 static vector<vector<int>> testVectorVector =
44 return seq(1, i) | as<vector>();
48 auto square = [](int x) { return x * x; };
49 auto add = [](int a, int b) { return a + b; };
50 auto multiply = [](int a, int b) { return a * b; };
52 BENCHMARK(Sum_Basic_NoGen, iters) {
53 int limit = testSize.load();
56 for (int i = 0; i < limit; ++i) {
60 folly::doNotOptimizeAway(s);
63 BENCHMARK_RELATIVE(Sum_Basic_Gen, iters) {
64 int limit = testSize.load();
67 s += range(0, limit) | sum;
69 folly::doNotOptimizeAway(s);
74 BENCHMARK(Sum_Vector_NoGen, iters) {
77 for (auto& i : testVector) {
81 folly::doNotOptimizeAway(s);
84 BENCHMARK_RELATIVE(Sum_Vector_Gen, iters) {
87 s += from(testVector) | sum;
89 folly::doNotOptimizeAway(s);
94 BENCHMARK(Count_Vector_NoGen, iters) {
97 for (auto& i : testVector) {
103 folly::doNotOptimizeAway(s);
106 BENCHMARK_RELATIVE(Count_Vector_Gen, iters) {
109 s += from(testVector)
111 return i * 2 < rand();
115 folly::doNotOptimizeAway(s);
118 BENCHMARK_DRAW_LINE()
120 BENCHMARK(Fib_Sum_NoGen, iters) {
123 auto fib = [](int limit) -> vector<int> {
127 for (int i = 0; i * 2 < limit; ++i) {
128 ret.push_back(a += b);
129 ret.push_back(b += a);
133 for (auto& v : fib(testSize.load())) {
137 folly::doNotOptimizeAway(s);
140 BENCHMARK_RELATIVE(Fib_Sum_Gen, iters) {
143 auto fib = GENERATOR(int, {
151 s += fib | take(testSize.load()) | sum;
153 folly::doNotOptimizeAway(s);
157 template<class Yield>
158 void operator()(Yield&& yield) const {
168 BENCHMARK_RELATIVE(Fib_Sum_Gen_Static, iters) {
171 auto fib = generator<int>(FibYielder());
172 s += fib | take(testSize.load()) | sum;
174 folly::doNotOptimizeAway(s);
177 BENCHMARK_DRAW_LINE()
179 BENCHMARK(VirtualGen_0Virtual, iters) {
182 auto numbers = seq(1, 10000);
183 auto squares = numbers | map(square);
184 auto quads = squares | map(square);
187 folly::doNotOptimizeAway(s);
190 BENCHMARK_RELATIVE(VirtualGen_1Virtual, iters) {
193 VirtualGen<int> numbers = seq(1, 10000);
194 auto squares = numbers | map(square);
195 auto quads = squares | map(square);
198 folly::doNotOptimizeAway(s);
201 BENCHMARK_RELATIVE(VirtualGen_2Virtual, iters) {
204 VirtualGen<int> numbers = seq(1, 10000);
205 VirtualGen<int> squares = numbers | map(square);
206 auto quads = squares | map(square);
209 folly::doNotOptimizeAway(s);
212 BENCHMARK_RELATIVE(VirtualGen_3Virtual, iters) {
215 VirtualGen<int> numbers = seq(1, 10000);
216 VirtualGen<int> squares = numbers | map(square);
217 VirtualGen<int> quads = squares | map(square);
220 folly::doNotOptimizeAway(s);
223 BENCHMARK_DRAW_LINE()
225 BENCHMARK(Concat_NoGen, iters) {
228 for (auto& v : testVectorVector) {
234 folly::doNotOptimizeAway(s);
237 BENCHMARK_RELATIVE(Concat_Gen, iters) {
240 s += from(testVectorVector) | rconcat | sum;
242 folly::doNotOptimizeAway(s);
245 BENCHMARK_DRAW_LINE()
247 BENCHMARK(Composed_NoGen, iters) {
250 for (auto& i : testVector) {
254 folly::doNotOptimizeAway(s);
257 BENCHMARK_RELATIVE(Composed_Gen, iters) {
259 auto sumSq = map(square) | sum;
261 s += from(testVector) | sumSq;
263 folly::doNotOptimizeAway(s);
266 BENCHMARK_RELATIVE(Composed_GenRegular, iters) {
269 s += from(testVector) | map(square) | sum;
271 folly::doNotOptimizeAway(s);
274 BENCHMARK_DRAW_LINE()
278 const char* const kLine = "The quick brown fox jumped over the lazy dog.\n";
279 const size_t kLineCount = 10000;
280 std::string bigLines;
281 const size_t kSmallLineSize = 17;
282 std::vector<std::string> smallLines;
284 void initStringResplitterBenchmark() {
285 bigLines.reserve(kLineCount * strlen(kLine));
286 for (size_t i = 0; i < kLineCount; ++i) {
289 size_t remaining = bigLines.size();
292 size_t n = std::min(kSmallLineSize, remaining);
293 smallLines.push_back(bigLines.substr(pos, n));
299 size_t len(folly::StringPiece s) { return s.size(); }
303 BENCHMARK(StringResplitter_Big, iters) {
306 s += from({bigLines}) | resplit('\n') | map(&len) | sum;
308 folly::doNotOptimizeAway(s);
311 BENCHMARK_RELATIVE(StringResplitter_Small, iters) {
314 s += from(smallLines) | resplit('\n') | map(&len) | sum;
316 folly::doNotOptimizeAway(s);
319 BENCHMARK_DRAW_LINE()
321 BENCHMARK(ByLine_Pipes, iters) {
327 CHECK_ERR(::pipe(p));
330 thread = std::thread([wfd, iters] {
332 PCHECK(::write(wfd, &x, 1) == 1); // signal startup
333 FILE* f = fdopen(wfd, "w");
335 for (int i = 1; i <= iters; ++i) {
336 fprintf(f, "%d\n", i);
341 PCHECK(::read(rfd, &buf, 1) == 1); // wait for startup
344 auto s = byLine(rfd) | eachTo<int64_t>() | sum;
345 folly::doNotOptimizeAway(s);
349 CHECK_EQ(s, int64_t(iters) * (iters + 1) / 2);
354 // Results from a dual core Xeon L5520 @ 2.27GHz:
356 // ============================================================================
357 // folly/experimental/test/GenBenchmark.cpp relative time/iter iters/s
358 // ============================================================================
359 // Sum_Basic_NoGen 301.60ns 3.32M
360 // Sum_Basic_Gen 104.27% 289.24ns 3.46M
361 // ----------------------------------------------------------------------------
362 // Sum_Vector_NoGen 200.33ns 4.99M
363 // Sum_Vector_Gen 99.81% 200.70ns 4.98M
364 // ----------------------------------------------------------------------------
365 // Count_Vector_NoGen 12.37us 80.84K
366 // Count_Vector_Gen 103.09% 12.00us 83.33K
367 // ----------------------------------------------------------------------------
368 // Fib_Sum_NoGen 3.66us 273.21K
369 // Fib_Sum_Gen 43.06% 8.50us 117.65K
370 // Fib_Sum_Gen_Static 87.81% 4.17us 239.89K
371 // ----------------------------------------------------------------------------
372 // VirtualGen_0Virtual 10.04us 99.61K
373 // VirtualGen_1Virtual 29.59% 33.93us 29.47K
374 // VirtualGen_2Virtual 20.45% 49.10us 20.37K
375 // VirtualGen_3Virtual 15.49% 64.82us 15.43K
376 // ----------------------------------------------------------------------------
377 // Concat_NoGen 2.50us 400.37K
378 // Concat_Gen 102.50% 2.44us 410.37K
379 // ----------------------------------------------------------------------------
380 // Composed_NoGen 549.54ns 1.82M
381 // Composed_Gen 101.39% 542.00ns 1.85M
382 // Composed_GenRegular 99.66% 551.40ns 1.81M
383 // ============================================================================
385 int main(int argc, char *argv[]) {
386 google::ParseCommandLineFlags(&argc, &argv, true);
387 initStringResplitterBenchmark();