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