2 * Copyright 2016 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.
16 /* -*- Mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
18 #include <folly/Singleton.h>
23 #include <folly/Benchmark.h>
24 #include <folly/Memory.h>
25 #include <folly/portability/GFlags.h>
27 using namespace folly;
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);
37 int normal_singleton_value = 0;
38 int* getNormalSingleton() {
39 doNotOptimizeAway(&normal_singleton_value);
40 return &normal_singleton_value;
43 struct BenchmarkSingleton {
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);
52 for (auto& thread : threads) {
57 void normalSingleton(size_t n) {
58 for (size_t i = 0; i < n; ++ i) {
59 doNotOptimizeAway(getNormalSingleton());
63 BENCHMARK(NormalSingleton, n) {
67 BENCHMARK(NormalSingleton4Threads, n) {
73 void meyersSingleton(size_t n) {
74 for (size_t i = 0; i < n; ++i) {
75 doNotOptimizeAway(getMeyersSingleton());
80 BENCHMARK(MeyersSingleton, n) {
84 BENCHMARK(MeyersSingleton4Threads, n) {
90 struct BenchmarkTag {};
91 template <typename T, typename Tag = detail::DefaultTag>
92 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
96 struct TryGetFastTag{};
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;
103 void follySingletonRaw(size_t n) {
104 for (size_t i = 0; i < n; ++i) {
105 SingletonBenchmark<BenchmarkSingleton, GetTag>::get();
109 BENCHMARK(FollySingletonRaw, n) {
110 follySingletonRaw(n);
113 BENCHMARK(FollySingletonRaw4Threads, n) {
115 follySingletonRaw(n);
119 void follySingletonTryGet(size_t n) {
120 for (size_t i = 0; i < n; ++i) {
121 SingletonBenchmark<BenchmarkSingleton, TryGetTag>::try_get();
125 BENCHMARK(FollySingletonTryGet, n) {
126 follySingletonTryGet(n);
129 BENCHMARK(FollySingletonTryGet4Threads, n) {
131 follySingletonTryGet(n);
135 void follySingletonTryGetFast(size_t n) {
136 for (size_t i = 0; i < n; ++i) {
137 SingletonBenchmark<BenchmarkSingleton, TryGetFastTag>::try_get_fast();
141 BENCHMARK(FollySingletonTryGetFast, n) {
142 follySingletonTryGetFast(n);
145 BENCHMARK(FollySingletonTryGetFast4Threads, n) {
147 follySingletonTryGetFast(n);
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
157 folly::runBenchmarks();