2 * Copyright 2017-present 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) {
73 void benchmarkSharedPtrCopy(size_t numThreads, size_t iters) {
74 auto p = std::make_shared<int>(1);
75 parallelRun([&] { return p; }, numThreads, iters);
78 void benchmarkWeakPtrLock(size_t numThreads, size_t iters) {
79 auto p = std::make_shared<int>(1);
80 std::weak_ptr<int> wp = p;
81 parallelRun([&] { return wp.lock(); }, numThreads, iters);
84 void benchmarkAtomicSharedPtrCopy(size_t numThreads, size_t iters) {
85 auto s = std::make_shared<int>(1);
86 folly::atomic_shared_ptr<int> p;
88 parallelRun([&] { return p.load(); }, numThreads, iters);
91 void benchmarkCoreCachedSharedPtrGet(size_t numThreads, size_t iters) {
92 folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
93 parallelRun([&] { return p.get(); }, numThreads, iters);
96 void benchmarkCoreCachedWeakPtrLock(size_t numThreads, size_t iters) {
97 folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
98 folly::CoreCachedWeakPtr<int> wp(p);
99 parallelRun([&] { return wp.get().lock(); }, numThreads, iters);
102 void benchmarkAtomicCoreCachedSharedPtrGet(size_t numThreads, size_t iters) {
103 folly::AtomicCoreCachedSharedPtr<int> p(std::make_shared<int>(1));
104 parallelRun([&] { return p.get(); }, numThreads, iters);
109 BENCHMARK(SharedPtrSingleThread, n) {
110 benchmarkSharedPtrCopy(1, n);
112 BENCHMARK(WeakPtrSingleThread, n) {
113 benchmarkWeakPtrLock(1, n);
115 BENCHMARK(AtomicSharedPtrSingleThread, n) {
116 benchmarkAtomicSharedPtrCopy(1, n);
118 BENCHMARK(CoreCachedSharedPtrSingleThread, n) {
119 benchmarkCoreCachedSharedPtrGet(1, n);
121 BENCHMARK(CoreCachedWeakPtrSingleThread, n) {
122 benchmarkCoreCachedWeakPtrLock(1, n);
124 BENCHMARK(AtomicCoreCachedSharedPtrSingleThread, n) {
125 benchmarkAtomicCoreCachedSharedPtrGet(1, n);
128 BENCHMARK_DRAW_LINE();
130 BENCHMARK(SharedPtr4Threads, n) {
131 benchmarkSharedPtrCopy(4, n);
133 BENCHMARK(WeakPtr4Threads, n) {
134 benchmarkWeakPtrLock(4, n);
136 BENCHMARK(AtomicSharedPtr4Threads, n) {
137 benchmarkAtomicSharedPtrCopy(4, n);
139 BENCHMARK(CoreCachedSharedPtr4Threads, n) {
140 benchmarkCoreCachedSharedPtrGet(4, n);
142 BENCHMARK(CoreCachedWeakPtr4Threads, n) {
143 benchmarkCoreCachedWeakPtrLock(4, n);
145 BENCHMARK(AtomicCoreCachedSharedPtr4Threads, n) {
146 benchmarkAtomicCoreCachedSharedPtrGet(4, n);
149 BENCHMARK_DRAW_LINE();
151 BENCHMARK(SharedPtr16Threads, n) {
152 benchmarkSharedPtrCopy(16, n);
154 BENCHMARK(WeakPtr16Threads, n) {
155 benchmarkWeakPtrLock(16, n);
157 BENCHMARK(AtomicSharedPtr16Threads, n) {
158 benchmarkAtomicSharedPtrCopy(16, n);
160 BENCHMARK(CoreCachedSharedPtr16Threads, n) {
161 benchmarkCoreCachedSharedPtrGet(16, n);
163 BENCHMARK(CoreCachedWeakPtr16Threads, n) {
164 benchmarkCoreCachedWeakPtrLock(16, n);
166 BENCHMARK(AtomicCoreCachedSharedPtr16Threads, n) {
167 benchmarkAtomicCoreCachedSharedPtrGet(16, n);
170 BENCHMARK_DRAW_LINE();
172 BENCHMARK(SharedPtrSingleThreadReset, n) {
173 auto p = std::make_shared<int>(1);
174 parallelRun([&] { p = std::make_shared<int>(1); }, 1, n);
176 BENCHMARK(AtomicSharedPtrSingleThreadReset, n) {
177 auto s = std::make_shared<int>(1);
178 folly::atomic_shared_ptr<int> p;
180 parallelRun([&] { p.store(std::make_shared<int>(1)); }, 1, n);
182 BENCHMARK(CoreCachedSharedPtrSingleThreadReset, n) {
183 folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
184 parallelRun([&] { p.reset(std::make_shared<int>(1)); }, 1, n);
186 BENCHMARK(AtomicCoreCachedSharedPtrSingleThreadReset, n) {
187 folly::AtomicCoreCachedSharedPtr<int> p(std::make_shared<int>(1));
188 parallelRun([&] { p.reset(std::make_shared<int>(1)); }, 1, n);
191 int main(int argc, char** argv) {
192 testing::InitGoogleTest(&argc, argv);
193 gflags::ParseCommandLineFlags(&argc, &argv, true);
195 auto ret = RUN_ALL_TESTS();
196 if (ret == 0 && FLAGS_benchmark) {
197 folly::runBenchmarks();