A core-cached shared_ptr
[folly.git] / folly / concurrency / test / CoreCachedSharedPtrTest.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
17 #include <memory>
18 #include <thread>
19 #include <vector>
20
21 #include <folly/Benchmark.h>
22 #include <folly/Portability.h>
23 #include <folly/concurrency/CoreCachedSharedPtr.h>
24 #include <folly/portability/GTest.h>
25
26 TEST(CoreCachedSharedPtr, Basic) {
27   auto p = std::make_shared<int>(1);
28   std::weak_ptr<int> wp(p);
29
30   folly::CoreCachedSharedPtr<int> cached(p);
31   folly::CoreCachedWeakPtr<int> wcached(cached);
32
33   std::shared_ptr<int> p2 = cached.get();
34   std::weak_ptr<int> wp2 = wcached.get();
35   ASSERT_TRUE(p2 != nullptr);
36   ASSERT_EQ(*p2, 1);
37   ASSERT_FALSE(wp2.expired());
38
39   p.reset();
40   cached.reset();
41   // p2 should survive.
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.
45
46   p2.reset();
47   ASSERT_TRUE(wp.expired());
48   ASSERT_TRUE(wp2.expired());
49 }
50
51 namespace {
52
53 template <class Operation>
54 void parallelRun(Operation op, size_t numThreads, size_t iters) {
55   std::vector<std::thread> threads;
56
57   // Prevent the compiler from hoisting code out of the loop.
58   auto opNoinline = [&]() FOLLY_NOINLINE { op(); };
59
60   for (size_t t = 0; t < numThreads; ++t) {
61     threads.emplace_back([&] {
62       for (size_t i = 0; i < iters; ++i) {
63         opNoinline();
64       }
65     });
66   }
67
68   for (auto& t : threads)
69     t.join();
70 }
71
72 void benchmarkSharedPtrCopy(size_t numThreads, size_t iters) {
73   auto p = std::make_shared<int>(1);
74   parallelRun([&] { return p; }, numThreads, iters);
75 }
76
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);
81 }
82
83 void benchmarkCoreCachedSharedPtrGet(size_t numThreads, size_t iters) {
84   folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
85   parallelRun([&] { return p.get(); }, numThreads, iters);
86 }
87
88 void benchmarkCoreCachedWeakPtrLock(size_t numThreads, size_t iters) {
89   folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
90   folly::CoreCachedWeakPtr<int> wp(p);
91   parallelRun([&] { return wp.get().lock(); }, numThreads, iters);
92 }
93
94 } // namespace
95
96 BENCHMARK(SharedPtrSingleThread, n) {
97   benchmarkSharedPtrCopy(1, n);
98 }
99 BENCHMARK(WeakPtrSingleThread, n) {
100   benchmarkWeakPtrLock(1, n);
101 }
102 BENCHMARK(CoreCachedSharedPtrSingleThread, n) {
103   benchmarkCoreCachedSharedPtrGet(1, n);
104 }
105 BENCHMARK(CoreCachedWeakPtrSingleThread, n) {
106   benchmarkCoreCachedWeakPtrLock(1, n);
107 }
108
109 BENCHMARK_DRAW_LINE();
110
111 BENCHMARK(SharedPtr4Threads, n) {
112   benchmarkSharedPtrCopy(4, n);
113 }
114 BENCHMARK(WeakPtr4Threads, n) {
115   benchmarkWeakPtrLock(4, n);
116 }
117 BENCHMARK(CoreCachedSharedPtr4Threads, n) {
118   benchmarkCoreCachedSharedPtrGet(4, n);
119 }
120 BENCHMARK(CoreCachedWeakPtr4Threads, n) {
121   benchmarkCoreCachedWeakPtrLock(4, n);
122 }
123
124 BENCHMARK_DRAW_LINE();
125
126 BENCHMARK(SharedPtr16Threads, n) {
127   benchmarkSharedPtrCopy(16, n);
128 }
129 BENCHMARK(WeakPtr16Threads, n) {
130   benchmarkWeakPtrLock(16, n);
131 }
132 BENCHMARK(CoreCachedSharedPtr16Threads, n) {
133   benchmarkCoreCachedSharedPtrGet(16, n);
134 }
135 BENCHMARK(CoreCachedWeakPtr16Threads, n) {
136   benchmarkCoreCachedWeakPtrLock(16, n);
137 }
138
139 int main(int argc, char** argv) {
140   testing::InitGoogleTest(&argc, argv);
141   gflags::ParseCommandLineFlags(&argc, &argv, true);
142
143   auto ret = RUN_ALL_TESTS();
144   if (ret == 0 && FLAGS_benchmark) {
145     folly::runBenchmarks();
146   }
147
148   return ret;
149 }