Consistently have the namespace closing comment
[folly.git] / folly / test / BenchmarkTest.cpp
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <folly/Benchmark.h>
18 #include <folly/String.h>
19 #include <folly/container/Foreach.h>
20 #include <algorithm>
21 #include <iostream>
22 #include <numeric>
23 #include <random>
24 #include <vector>
25 using namespace folly;
26 using namespace std;
27
28 void fun() {
29   static double x = 1;
30   ++x;
31   doNotOptimizeAway(x);
32 }
33 BENCHMARK(bmFun) { fun(); }
34 BENCHMARK(bmRepeatedFun, n) {
35   FOR_EACH_RANGE (i, 0, n) {
36     fun();
37   }
38 }
39 BENCHMARK_DRAW_LINE()
40
41 BENCHMARK(gun) {
42   static double x = 1;
43   x *= 2000;
44   doNotOptimizeAway(x);
45 }
46
47 BENCHMARK_DRAW_LINE()
48
49 BENCHMARK(optimizerCanDiscardTrivial, n) {
50   long x = 0;
51   for (long i = 0; i < n; ++i) {
52     for (long j = 0; j < 10000; ++j) {
53       x += j;
54     }
55   }
56 }
57
58 BENCHMARK(optimizerCanPowerReduceInner1Trivial, n) {
59   long x = 0;
60   for (long i = 0; i < n; ++i) {
61     for (long j = 0; j < 10000; ++j) {
62       x += i + j;
63     }
64     doNotOptimizeAway(x);
65   }
66 }
67
68 BENCHMARK(optimizerCanPowerReduceInner2Trivial, n) {
69   long x = 0;
70   for (long i = 0; i < n; ++i) {
71     makeUnpredictable(i);
72     for (long j = 0; j < 10000; ++j) {
73       x += i + j;
74     }
75   }
76   doNotOptimizeAway(x);
77 }
78
79 BENCHMARK(optimizerDisabled1Trivial, n) {
80   long x = 0;
81   for (long i = 0; i < n; ++i) {
82     for (long j = 0; j < 10000; ++j) {
83       x += i + j;
84       doNotOptimizeAway(x);
85     }
86   }
87 }
88
89 BENCHMARK(optimizerDisabled2Trivial, n) {
90   long x = 0;
91   for (long i = 0; i < n; ++i) {
92     makeUnpredictable(i);
93     for (long j = 0; j < 10000; ++j) {
94       makeUnpredictable(j);
95       x += i + j;
96     }
97   }
98   doNotOptimizeAway(x);
99 }
100
101 BENCHMARK(optimizerCanPowerReduceInner1TrivialPtr, n) {
102   long x = 0;
103   for (long i = 0; i < n; ++i) {
104     for (long j = 0; j < 10000; ++j) {
105       x += i + j;
106     }
107     doNotOptimizeAway(&x);
108   }
109 }
110
111 BENCHMARK(optimizerCanPowerReduceInner2TrivialPtr, n) {
112   long x = 0;
113   for (long i = 0; i < n; ++i) {
114     makeUnpredictable(i);
115     for (long j = 0; j < 10000; ++j) {
116       x += i + j;
117     }
118   }
119   doNotOptimizeAway(&x);
120 }
121
122 BENCHMARK(optimizerDisabled1TrivialPtr, n) {
123   long x = 0;
124   for (long i = 0; i < n; ++i) {
125     for (long j = 0; j < 10000; ++j) {
126       x += i + j;
127       doNotOptimizeAway(&x);
128     }
129   }
130 }
131
132 namespace {
133 class NonTrivialLong {
134  public:
135   explicit NonTrivialLong(long v) : value_(v) {}
136   virtual ~NonTrivialLong() {}
137
138   void operator++() {
139     ++value_;
140   }
141   void operator+=(long rhs) {
142     value_ += rhs;
143   }
144   void operator+=(const NonTrivialLong& rhs) {
145     value_ += rhs.value_;
146   }
147   bool operator<(long rhs) {
148     return value_ < rhs;
149   }
150   NonTrivialLong operator+(const NonTrivialLong& rhs) {
151     return NonTrivialLong(value_ + rhs.value_);
152   }
153
154  private:
155   long value_;
156   long otherStuff_[3];
157 };
158 } // namespace
159
160 BENCHMARK(optimizerCanDiscardNonTrivial, n) {
161   NonTrivialLong x(0);
162   for (NonTrivialLong i(0); i < n; ++i) {
163     for (NonTrivialLong j(0); j < 10000; ++j) {
164       x += j;
165     }
166   }
167 }
168
169 BENCHMARK(optimizerCanPowerReduceInner1NonTrivial, n) {
170   NonTrivialLong x(0);
171   for (NonTrivialLong i(0); i < n; ++i) {
172     for (NonTrivialLong j(0); j < 10000; ++j) {
173       x += i + j;
174     }
175     doNotOptimizeAway(x);
176   }
177 }
178
179 BENCHMARK(optimizerCanPowerReduceInner2NonTrivial, n) {
180   NonTrivialLong x(0);
181   for (NonTrivialLong i(0); i < n; ++i) {
182     makeUnpredictable(i);
183     for (NonTrivialLong j(0); j < 10000; ++j) {
184       x += i + j;
185     }
186   }
187   doNotOptimizeAway(x);
188 }
189
190 BENCHMARK(optimizerDisabled1NonTrivial, n) {
191   NonTrivialLong x(0);
192   for (NonTrivialLong i(0); i < n; ++i) {
193     for (NonTrivialLong j(0); j < 10000; ++j) {
194       x += i + j;
195       doNotOptimizeAway(x);
196     }
197   }
198 }
199
200 BENCHMARK(optimizerDisabled2NonTrivial, n) {
201   NonTrivialLong x(0);
202   for (NonTrivialLong i(0); i < n; ++i) {
203     makeUnpredictable(i);
204     for (NonTrivialLong j(0); j < 10000; ++j) {
205       makeUnpredictable(j);
206       x += i + j;
207     }
208   }
209   doNotOptimizeAway(x);
210 }
211
212 BENCHMARK(optimizerCanPowerReduceInner1NonTrivialPtr, n) {
213   NonTrivialLong x(0);
214   for (NonTrivialLong i(0); i < n; ++i) {
215     for (NonTrivialLong j(0); j < 10000; ++j) {
216       x += i + j;
217     }
218     doNotOptimizeAway(&x);
219   }
220 }
221
222 BENCHMARK(optimizerCanPowerReduceInner2NonTrivialPtr, n) {
223   NonTrivialLong x(0);
224   for (NonTrivialLong i(0); i < n; ++i) {
225     makeUnpredictable(i);
226     for (NonTrivialLong j(0); j < 10000; ++j) {
227       x += i + j;
228     }
229   }
230   doNotOptimizeAway(&x);
231 }
232
233 BENCHMARK(optimizerDisabled1NonTrivialPtr, n) {
234   NonTrivialLong x(0);
235   for (NonTrivialLong i(0); i < n; ++i) {
236     for (NonTrivialLong j(0); j < 10000; ++j) {
237       x += i + j;
238       doNotOptimizeAway(&x);
239     }
240   }
241 }
242
243 BENCHMARK_DRAW_LINE()
244
245 BENCHMARK(baselinevector) {
246   vector<int> v;
247
248   BENCHMARK_SUSPEND {
249     v.resize(1000);
250   }
251
252   FOR_EACH_RANGE (i, 0, 100) {
253     v.push_back(42);
254   }
255 }
256
257 BENCHMARK_RELATIVE(bmVector) {
258   vector<int> v;
259   FOR_EACH_RANGE (i, 0, 100) {
260     v.resize(v.size() + 1, 42);
261   }
262 }
263
264 BENCHMARK_DRAW_LINE()
265
266 BENCHMARK(superslow) {
267   sleep(1);
268 }
269
270 BENCHMARK_DRAW_LINE()
271
272 BENCHMARK(noMulti) {
273   fun();
274 }
275
276 BENCHMARK_MULTI(multiSimple) {
277   FOR_EACH_RANGE (i, 0, 10) {
278     fun();
279   }
280   return 10;
281 }
282
283 BENCHMARK_RELATIVE_MULTI(multiSimpleRel) {
284   FOR_EACH_RANGE (i, 0, 10) {
285     fun();
286     fun();
287   }
288   return 10;
289 }
290
291 BENCHMARK_MULTI(multiIterArgs, iter) {
292   FOR_EACH_RANGE (i, 0, 10 * iter) {
293     fun();
294   }
295   return 10 * iter;
296 }
297
298 BENCHMARK_RELATIVE_MULTI(multiIterArgsRel, iter) {
299   FOR_EACH_RANGE (i, 0, 10 * iter) {
300     fun();
301     fun();
302   }
303   return 10 * iter;
304 }
305
306 unsigned paramMulti(unsigned iter, unsigned num) {
307   for (unsigned i = 0; i < iter; ++i) {
308     for (unsigned j = 0; j < num; ++j) {
309       fun();
310     }
311   }
312   return num * iter;
313 }
314
315 unsigned paramMultiRel(unsigned iter, unsigned num) {
316   for (unsigned i = 0; i < iter; ++i) {
317     for (unsigned j = 0; j < num; ++j) {
318       fun();
319       fun();
320     }
321   }
322   return num * iter;
323 }
324
325 BENCHMARK_PARAM_MULTI(paramMulti, 1);
326 BENCHMARK_RELATIVE_PARAM_MULTI(paramMultiRel, 1);
327
328 BENCHMARK_PARAM_MULTI(paramMulti, 5);
329 BENCHMARK_RELATIVE_PARAM_MULTI(paramMultiRel, 5);
330
331 BENCHMARK_DRAW_LINE();
332
333 BENCHMARK(BenchmarkSuspender_dismissing_void, iter) {
334   BenchmarkSuspender braces;
335   mt19937_64 rng;
336   while (iter--) {
337     vector<size_t> v(1 << 12, 0);
338     iota(v.begin(), v.end(), 0);
339     shuffle(v.begin(), v.end(), rng);
340     braces.dismissing([&] {
341         sort(v.begin(), v.end());
342     });
343   }
344 }
345
346 BENCHMARK(BenchmarkSuspender_dismissing_value, iter) {
347   BenchmarkSuspender braces;
348   mt19937_64 rng;
349   while (iter--) {
350     vector<size_t> v(1 << 12, 0);
351     iota(v.begin(), v.end(), 0);
352     shuffle(v.begin(), v.end(), rng);
353     auto s = braces.dismissing([&] {
354         sort(v.begin(), v.end());
355         return accumulate(v.begin(), v.end(), 0, [](size_t a, size_t e) {
356             return a + e;
357         });
358     });
359     doNotOptimizeAway(s);
360   }
361 }
362
363 int main(int argc, char** argv) {
364   gflags::ParseCommandLineFlags(&argc, &argv, true);
365   runBenchmarks();
366   runBenchmarksOnFlag();
367 }