2 * Copyright 2017 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.
21 #include <folly/Benchmark.h>
22 #include <folly/Portability.h>
23 #include <folly/concurrency/CoreCachedSharedPtr.h>
24 #include <folly/portability/GTest.h>
26 TEST(CoreCachedSharedPtr, Basic) {
27 auto p = std::make_shared<int>(1);
28 std::weak_ptr<int> wp(p);
30 folly::CoreCachedSharedPtr<int> cached(p);
31 folly::CoreCachedWeakPtr<int> wcached(cached);
33 std::shared_ptr<int> p2 = cached.get();
34 std::weak_ptr<int> wp2 = wcached.get();
35 ASSERT_TRUE(p2 != nullptr);
37 ASSERT_FALSE(wp2.expired());
42 ASSERT_FALSE(wp.expired());
43 // Here we don't know anything about wp2: could be expired even if
44 // there is a living reference to the main object.
47 ASSERT_TRUE(wp.expired());
48 ASSERT_TRUE(wp2.expired());
53 template <class Operation>
54 void parallelRun(Operation op, size_t numThreads, size_t iters) {
55 std::vector<std::thread> threads;
57 // Prevent the compiler from hoisting code out of the loop.
58 auto opNoinline = [&]() FOLLY_NOINLINE { op(); };
60 for (size_t t = 0; t < numThreads; ++t) {
61 threads.emplace_back([&] {
62 for (size_t i = 0; i < iters; ++i) {
68 for (auto& t : threads)
72 void benchmarkSharedPtrCopy(size_t numThreads, size_t iters) {
73 auto p = std::make_shared<int>(1);
74 parallelRun([&] { return p; }, numThreads, iters);
77 void benchmarkWeakPtrLock(size_t numThreads, size_t iters) {
78 auto p = std::make_shared<int>(1);
79 std::weak_ptr<int> wp = p;
80 parallelRun([&] { return wp.lock(); }, numThreads, iters);
83 void benchmarkAtomicSharedPtrCopy(size_t numThreads, size_t iters) {
84 auto s = std::make_shared<int>(1);
85 folly::atomic_shared_ptr<int> p;
87 parallelRun([&] { return p.load(); }, numThreads, iters);
90 void benchmarkCoreCachedSharedPtrGet(size_t numThreads, size_t iters) {
91 folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
92 parallelRun([&] { return p.get(); }, numThreads, iters);
95 void benchmarkCoreCachedWeakPtrLock(size_t numThreads, size_t iters) {
96 folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
97 folly::CoreCachedWeakPtr<int> wp(p);
98 parallelRun([&] { return wp.get().lock(); }, numThreads, iters);
101 void benchmarkAtomicCoreCachedSharedPtrGet(size_t numThreads, size_t iters) {
102 folly::AtomicCoreCachedSharedPtr<int> p(std::make_shared<int>(1));
103 parallelRun([&] { return p.get(); }, numThreads, iters);
108 BENCHMARK(SharedPtrSingleThread, n) {
109 benchmarkSharedPtrCopy(1, n);
111 BENCHMARK(WeakPtrSingleThread, n) {
112 benchmarkWeakPtrLock(1, n);
114 BENCHMARK(AtomicSharedPtrSingleThread, n) {
115 benchmarkAtomicSharedPtrCopy(1, n);
117 BENCHMARK(CoreCachedSharedPtrSingleThread, n) {
118 benchmarkCoreCachedSharedPtrGet(1, n);
120 BENCHMARK(CoreCachedWeakPtrSingleThread, n) {
121 benchmarkCoreCachedWeakPtrLock(1, n);
123 BENCHMARK(AtomicCoreCachedSharedPtrSingleThread, n) {
124 benchmarkAtomicCoreCachedSharedPtrGet(1, n);
127 BENCHMARK_DRAW_LINE();
129 BENCHMARK(SharedPtr4Threads, n) {
130 benchmarkSharedPtrCopy(4, n);
132 BENCHMARK(WeakPtr4Threads, n) {
133 benchmarkWeakPtrLock(4, n);
135 BENCHMARK(AtomicSharedPtr4Threads, n) {
136 benchmarkAtomicSharedPtrCopy(4, n);
138 BENCHMARK(CoreCachedSharedPtr4Threads, n) {
139 benchmarkCoreCachedSharedPtrGet(4, n);
141 BENCHMARK(CoreCachedWeakPtr4Threads, n) {
142 benchmarkCoreCachedWeakPtrLock(4, n);
144 BENCHMARK(AtomicCoreCachedSharedPtr4Threads, n) {
145 benchmarkAtomicCoreCachedSharedPtrGet(4, n);
148 BENCHMARK_DRAW_LINE();
150 BENCHMARK(SharedPtr16Threads, n) {
151 benchmarkSharedPtrCopy(16, n);
153 BENCHMARK(WeakPtr16Threads, n) {
154 benchmarkWeakPtrLock(16, n);
156 BENCHMARK(AtomicSharedPtr16Threads, n) {
157 benchmarkAtomicSharedPtrCopy(16, n);
159 BENCHMARK(CoreCachedSharedPtr16Threads, n) {
160 benchmarkCoreCachedSharedPtrGet(16, n);
162 BENCHMARK(CoreCachedWeakPtr16Threads, n) {
163 benchmarkCoreCachedWeakPtrLock(16, n);
165 BENCHMARK(AtomicCoreCachedSharedPtr16Threads, n) {
166 benchmarkAtomicCoreCachedSharedPtrGet(16, n);
169 BENCHMARK_DRAW_LINE();
171 BENCHMARK(SharedPtrSingleThreadReset, n) {
172 auto p = std::make_shared<int>(1);
173 parallelRun([&] { p = std::make_shared<int>(1); }, 1, n);
175 BENCHMARK(AtomicSharedPtrSingleThreadReset, n) {
176 auto s = std::make_shared<int>(1);
177 folly::atomic_shared_ptr<int> p;
179 parallelRun([&] { p.store(std::make_shared<int>(1)); }, 1, n);
181 BENCHMARK(CoreCachedSharedPtrSingleThreadReset, n) {
182 folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
183 parallelRun([&] { p.reset(std::make_shared<int>(1)); }, 1, n);
185 BENCHMARK(AtomicCoreCachedSharedPtrSingleThreadReset, n) {
186 folly::AtomicCoreCachedSharedPtr<int> p(std::make_shared<int>(1));
187 parallelRun([&] { p.reset(std::make_shared<int>(1)); }, 1, n);
190 int main(int argc, char** argv) {
191 testing::InitGoogleTest(&argc, argv);
192 gflags::ParseCommandLineFlags(&argc, &argv, true);
194 auto ret = RUN_ALL_TESTS();
195 if (ret == 0 && FLAGS_benchmark) {
196 folly::runBenchmarks();