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