fix flaky ConnectTFOTimeout and ConnectTFOFallbackTimeout tests
[folly.git] / folly / test / SingletonBenchmark.cpp
1 /*
2  * Copyright 2016 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 /* -*- Mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
17
18 #include <folly/Singleton.h>
19
20 #include <iostream>
21 #include <thread>
22
23 #include <folly/Benchmark.h>
24 #include <folly/Memory.h>
25 #include <folly/portability/GFlags.h>
26
27 using namespace folly;
28
29 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
30 // singleton.  Meyers are insanely fast, but (hopefully) Folly
31 // singletons are fast "enough."
32 int* getMeyersSingleton() {
33   static auto ret = new int(0);
34   return ret;
35 }
36
37 int normal_singleton_value = 0;
38 int* getNormalSingleton() {
39   doNotOptimizeAway(&normal_singleton_value);
40   return &normal_singleton_value;
41 }
42
43 struct BenchmarkSingleton {
44   int val = 0;
45 };
46
47 void run4Threads(std::function<void()> f) {
48   std::vector<std::thread> threads;
49   for (size_t i = 0; i < 4; ++ i) {
50     threads.emplace_back(f);
51   }
52   for (auto& thread : threads) {
53     thread.join();
54   }
55 }
56
57 void normalSingleton(size_t n) {
58   for (size_t i = 0; i < n; ++ i) {
59     doNotOptimizeAway(getNormalSingleton());
60   }
61 }
62
63 BENCHMARK(NormalSingleton, n) {
64   normalSingleton(n);
65 }
66
67 BENCHMARK(NormalSingleton4Threads, n) {
68   run4Threads([=]() {
69       normalSingleton(n);
70     });
71 }
72
73 void meyersSingleton(size_t n) {
74   for (size_t i = 0; i < n; ++i) {
75     doNotOptimizeAway(getMeyersSingleton());
76   }
77 }
78
79
80 BENCHMARK(MeyersSingleton, n) {
81   meyersSingleton(n);
82 }
83
84 BENCHMARK(MeyersSingleton4Threads, n) {
85   run4Threads([=]() {
86       meyersSingleton(n);
87     });
88 }
89
90 struct BenchmarkTag {};
91 template <typename T, typename Tag = detail::DefaultTag>
92 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
93
94 struct GetTag{};
95 struct TryGetTag{};
96 struct TryGetFastTag{};
97
98 SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
99 SingletonBenchmark<BenchmarkSingleton, TryGetTag> benchmark_singleton_try_get;
100 SingletonBenchmark<BenchmarkSingleton, TryGetFastTag>
101 benchmark_singleton_try_get_fast;
102
103 void follySingletonRaw(size_t n) {
104   for (size_t i = 0; i < n; ++i) {
105     SingletonBenchmark<BenchmarkSingleton, GetTag>::get();
106   }
107 }
108
109 BENCHMARK(FollySingletonRaw, n) {
110   follySingletonRaw(n);
111 }
112
113 BENCHMARK(FollySingletonRaw4Threads, n) {
114   run4Threads([=]() {
115       follySingletonRaw(n);
116     });
117 }
118
119 void follySingletonTryGet(size_t n) {
120   for (size_t i = 0; i < n; ++i) {
121     SingletonBenchmark<BenchmarkSingleton, TryGetTag>::try_get();
122   }
123 }
124
125 BENCHMARK(FollySingletonTryGet, n) {
126   follySingletonTryGet(n);
127 }
128
129 BENCHMARK(FollySingletonTryGet4Threads, n) {
130   run4Threads([=]() {
131       follySingletonTryGet(n);
132     });
133 }
134
135 void follySingletonTryGetFast(size_t n) {
136   for (size_t i = 0; i < n; ++i) {
137     SingletonBenchmark<BenchmarkSingleton, TryGetFastTag>::try_get_fast();
138   }
139 }
140
141 BENCHMARK(FollySingletonTryGetFast, n) {
142   follySingletonTryGetFast(n);
143 }
144
145 BENCHMARK(FollySingletonTryGetFast4Threads, n) {
146   run4Threads([=]() {
147       follySingletonTryGetFast(n);
148     });
149 }
150
151 int main(int argc, char** argv) {
152   gflags::ParseCommandLineFlags(&argc, &argv, true);
153   gflags::SetCommandLineOptionWithMode(
154     "bm_min_usec", "100000", gflags::SET_FLAG_IF_DEFAULT
155   );
156
157   folly::runBenchmarks();
158
159   return 0;
160 }