proxygen
CoreCachedSharedPtrTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present 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 // AtomicSharedPtr-detail.h only works with libstdc++, so skip these tests for
18 // other vendors
19 #ifdef FOLLY_USE_LIBSTDCPP
20 
21 #include <memory>
22 #include <thread>
23 #include <vector>
24 
25 #include <folly/Benchmark.h>
26 #include <folly/Portability.h>
29 
30 TEST(CoreCachedSharedPtr, Basic) {
31  auto p = std::make_shared<int>(1);
32  std::weak_ptr<int> wp(p);
33 
35  folly::CoreCachedWeakPtr<int> wcached(cached);
36 
37  std::shared_ptr<int> p2 = cached.get();
38  std::weak_ptr<int> wp2 = wcached.get();
39  ASSERT_TRUE(p2 != nullptr);
40  ASSERT_EQ(*p2, 1);
41  ASSERT_FALSE(wp2.expired());
42 
43  p.reset();
44  cached.reset();
45  // p2 should survive.
46  ASSERT_FALSE(wp.expired());
47  // Here we don't know anything about wp2: could be expired even if
48  // there is a living reference to the main object.
49 
50  p2.reset();
51  ASSERT_TRUE(wp.expired());
52  ASSERT_TRUE(wp2.expired());
53 }
54 
55 namespace {
56 
57 template <class Operation>
58 void parallelRun(Operation op, size_t numThreads, size_t iters) {
59  std::vector<std::thread> threads;
60 
61  // Prevent the compiler from hoisting code out of the loop.
62  auto opNoinline = [&]() FOLLY_NOINLINE { op(); };
63 
64  for (size_t t = 0; t < numThreads; ++t) {
65  threads.emplace_back([&] {
66  for (size_t i = 0; i < iters; ++i) {
67  opNoinline();
68  }
69  });
70  }
71 
72  for (auto& t : threads) {
73  t.join();
74  }
75 }
76 
77 void benchmarkSharedPtrCopy(size_t numThreads, size_t iters) {
78  auto p = std::make_shared<int>(1);
79  parallelRun([&] { return p; }, numThreads, iters);
80 }
81 
82 void benchmarkWeakPtrLock(size_t numThreads, size_t iters) {
83  auto p = std::make_shared<int>(1);
84  std::weak_ptr<int> wp = p;
85  parallelRun([&] { return wp.lock(); }, numThreads, iters);
86 }
87 
88 void benchmarkAtomicSharedPtrCopy(size_t numThreads, size_t iters) {
89  auto s = std::make_shared<int>(1);
91  p.store(s);
92  parallelRun([&] { return p.load(); }, numThreads, iters);
93 }
94 
95 void benchmarkCoreCachedSharedPtrGet(size_t numThreads, size_t iters) {
96  folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
97  parallelRun([&] { return p.get(); }, numThreads, iters);
98 }
99 
100 void benchmarkCoreCachedWeakPtrLock(size_t numThreads, size_t iters) {
101  folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
103  parallelRun([&] { return wp.get().lock(); }, numThreads, iters);
104 }
105 
106 void benchmarkAtomicCoreCachedSharedPtrGet(size_t numThreads, size_t iters) {
107  folly::AtomicCoreCachedSharedPtr<int> p(std::make_shared<int>(1));
108  parallelRun([&] { return p.get(); }, numThreads, iters);
109 }
110 
111 } // namespace
112 
113 BENCHMARK(SharedPtrSingleThread, n) {
114  benchmarkSharedPtrCopy(1, n);
115 }
116 BENCHMARK(WeakPtrSingleThread, n) {
117  benchmarkWeakPtrLock(1, n);
118 }
119 BENCHMARK(AtomicSharedPtrSingleThread, n) {
120  benchmarkAtomicSharedPtrCopy(1, n);
121 }
122 BENCHMARK(CoreCachedSharedPtrSingleThread, n) {
123  benchmarkCoreCachedSharedPtrGet(1, n);
124 }
125 BENCHMARK(CoreCachedWeakPtrSingleThread, n) {
126  benchmarkCoreCachedWeakPtrLock(1, n);
127 }
128 BENCHMARK(AtomicCoreCachedSharedPtrSingleThread, n) {
129  benchmarkAtomicCoreCachedSharedPtrGet(1, n);
130 }
131 
133 
134 BENCHMARK(SharedPtr4Threads, n) {
135  benchmarkSharedPtrCopy(4, n);
136 }
137 BENCHMARK(WeakPtr4Threads, n) {
138  benchmarkWeakPtrLock(4, n);
139 }
140 BENCHMARK(AtomicSharedPtr4Threads, n) {
141  benchmarkAtomicSharedPtrCopy(4, n);
142 }
143 BENCHMARK(CoreCachedSharedPtr4Threads, n) {
144  benchmarkCoreCachedSharedPtrGet(4, n);
145 }
146 BENCHMARK(CoreCachedWeakPtr4Threads, n) {
147  benchmarkCoreCachedWeakPtrLock(4, n);
148 }
149 BENCHMARK(AtomicCoreCachedSharedPtr4Threads, n) {
150  benchmarkAtomicCoreCachedSharedPtrGet(4, n);
151 }
152 
154 
155 BENCHMARK(SharedPtr16Threads, n) {
156  benchmarkSharedPtrCopy(16, n);
157 }
158 BENCHMARK(WeakPtr16Threads, n) {
159  benchmarkWeakPtrLock(16, n);
160 }
161 BENCHMARK(AtomicSharedPtr16Threads, n) {
162  benchmarkAtomicSharedPtrCopy(16, n);
163 }
164 BENCHMARK(CoreCachedSharedPtr16Threads, n) {
165  benchmarkCoreCachedSharedPtrGet(16, n);
166 }
167 BENCHMARK(CoreCachedWeakPtr16Threads, n) {
168  benchmarkCoreCachedWeakPtrLock(16, n);
169 }
170 BENCHMARK(AtomicCoreCachedSharedPtr16Threads, n) {
171  benchmarkAtomicCoreCachedSharedPtrGet(16, n);
172 }
173 
175 
176 BENCHMARK(SharedPtrSingleThreadReset, n) {
177  auto p = std::make_shared<int>(1);
178  parallelRun([&] { p = std::make_shared<int>(1); }, 1, n);
179 }
180 BENCHMARK(AtomicSharedPtrSingleThreadReset, n) {
181  auto s = std::make_shared<int>(1);
183  p.store(s);
184  parallelRun([&] { p.store(std::make_shared<int>(1)); }, 1, n);
185 }
186 BENCHMARK(CoreCachedSharedPtrSingleThreadReset, n) {
187  folly::CoreCachedSharedPtr<int> p(std::make_shared<int>(1));
188  parallelRun([&] { p.reset(std::make_shared<int>(1)); }, 1, n);
189 }
190 BENCHMARK(AtomicCoreCachedSharedPtrSingleThreadReset, n) {
191  folly::AtomicCoreCachedSharedPtr<int> p(std::make_shared<int>(1));
192  parallelRun([&] { p.reset(std::make_shared<int>(1)); }, 1, n);
193 }
194 
195 int main(int argc, char** argv) {
196  testing::InitGoogleTest(&argc, argv);
197  gflags::ParseCommandLineFlags(&argc, &argv, true);
198 
199  auto ret = RUN_ALL_TESTS();
200  if (ret == 0 && FLAGS_benchmark) {
202  }
203 
204  return ret;
205 }
206 
207 #endif // #ifdef FOLLY_USE_LIBSTDCPP
#define TEST(test_case_name, test_name)
Definition: gtest.h:2187
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: gtest.h:2232
void runBenchmarks()
Definition: Benchmark.cpp:456
std::vector< std::thread::id > threads
int main(void)
Definition: test.c:2834
#define FOLLY_NOINLINE
Definition: CPortability.h:142
char ** argv
#define BENCHMARK(name,...)
Definition: Benchmark.h:365
static set< string > s
void store(SharedPtr n, std::memory_order order=std::memory_order_seq_cst)
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: gtest.cc:5370
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
#define BENCHMARK_DRAW_LINE()
Definition: Benchmark.h:557