proxygen
ParkingLotBenchmark.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018-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 #include <thread>
17 
19 
20 #include <folly/Benchmark.h>
21 #include <folly/detail/Futex.h>
24 
25 DEFINE_uint64(threads, 32, "Number of threads for benchmark");
26 
27 using namespace folly;
28 using namespace folly::test;
29 
31 
32 BENCHMARK(FutexNoWaitersWake, iters) {
33  BenchmarkSuspender susp;
35  Barrier b(FLAGS_threads + 1);
36 
37  std::vector<std::thread> threads{FLAGS_threads};
38  for (auto& t : threads) {
39  t = std::thread([&]() {
40  b.wait();
41  for (auto i = 0u; i < iters; i++) {
42  detail::futexWake(&fu, 1);
43  }
44  });
45  }
46  susp.dismiss();
47  b.wait();
48 
49  for (auto& t : threads) {
50  t.join();
51  }
52 }
53 
54 BENCHMARK_RELATIVE(ParkingLotNoWaitersWake, iters) {
55  BenchmarkSuspender susp;
56  Barrier b(FLAGS_threads + 1);
57 
58  std::vector<std::thread> threads{FLAGS_threads};
59  for (auto& t : threads) {
60  t = std::thread([&]() {
61  b.wait();
62  for (auto i = 0u; i < iters; i++) {
63  lot.unpark(&lot, [](Unit) { return UnparkControl::RetainContinue; });
64  }
65  });
66  }
67  susp.dismiss();
68  b.wait();
69 
70  for (auto& t : threads) {
71  t.join();
72  }
73 }
74 
75 BENCHMARK(FutexWakeOne, iters) {
76  BenchmarkSuspender susp;
78  Barrier b(FLAGS_threads + 1);
79 
80  std::vector<std::thread> threads{FLAGS_threads};
81  for (auto& t : threads) {
82  t = std::thread([&]() {
83  b.wait();
84  while (true) {
85  detail::futexWait(&fu, 0);
86  if (fu.load(std::memory_order_relaxed)) {
87  return;
88  }
89  }
90  });
91  }
92  susp.dismiss();
93  b.wait();
94  for (auto i = 0u; i < iters; i++) {
95  detail::futexWake(&fu, 1);
96  }
97  fu.store(1);
98  detail::futexWake(&fu, threads.size());
99 
100  for (auto& t : threads) {
101  t.join();
102  }
103 }
104 
105 BENCHMARK_RELATIVE(ParkingLotWakeOne, iters) {
106  BenchmarkSuspender susp;
107  std::atomic<bool> done{false};
108  Barrier b(FLAGS_threads + 1);
109 
110  std::vector<std::thread> threads{FLAGS_threads};
111  for (auto& t : threads) {
112  t = std::thread([&]() {
113  b.wait();
114  while (true) {
115  Unit f;
116  lot.park(
117  &done,
118  f,
119  [&] { return done.load(std::memory_order_relaxed) == 0; },
120  [] {});
121  if (done.load(std::memory_order_relaxed)) {
122  return;
123  }
124  }
125  });
126  }
127  susp.dismiss();
128  b.wait();
129  for (auto i = 0u; i < iters; i++) {
130  lot.unpark(&done, [](Unit) { return UnparkControl::RemoveBreak; });
131  }
132  done = true;
133  lot.unpark(&done, [](Unit) { return UnparkControl::RemoveContinue; });
134 
135  for (auto& t : threads) {
136  t.join();
137  }
138 }
139 
140 BENCHMARK(FutexWakeAll, iters) {
141  BenchmarkSuspender susp;
142  Barrier b(FLAGS_threads + 1);
144  std::atomic<bool> done{false};
145 
146  std::vector<std::thread> threads{FLAGS_threads};
147  for (auto& t : threads) {
148  t = std::thread([&]() {
149  b.wait();
150  while (true) {
151  detail::futexWait(&fu, 0);
152  if (done.load(std::memory_order_relaxed)) {
153  return;
154  }
155  }
156  });
157  }
158  susp.dismiss();
159  b.wait();
160  for (auto i = 0u; i < iters; i++) {
161  detail::futexWake(&fu, threads.size());
162  }
163  fu.store(1);
164  done = true;
165  detail::futexWake(&fu, threads.size());
166 
167  for (auto& t : threads) {
168  t.join();
169  }
170 }
171 
172 BENCHMARK_RELATIVE(ParkingLotWakeAll, iters) {
173  BenchmarkSuspender susp;
174  Barrier b(FLAGS_threads + 1);
175  std::atomic<bool> done{false};
176 
177  std::vector<std::thread> threads{FLAGS_threads};
178  for (auto& t : threads) {
179  t = std::thread([&]() {
180  b.wait();
181  while (true) {
182  Unit f;
183  lot.park(
184  &done,
185  f,
186  [&] { return done.load(std::memory_order_relaxed) == 0; },
187  [] {});
188  if (done.load(std::memory_order_relaxed)) {
189  return;
190  }
191  }
192  });
193  }
194  susp.dismiss();
195  b.wait();
196  for (auto i = 0u; i < iters; i++) {
197  lot.unpark(&done, [](Unit) { return UnparkControl::RemoveContinue; });
198  }
199  done = true;
200  lot.unpark(&done, [](Unit) { return UnparkControl::RemoveContinue; });
201 
202  for (auto& t : threads) {
203  t.join();
204  }
205 }
206 
207 int main(int argc, char** argv) {
208  gflags::ParseCommandLineFlags(&argc, &argv, true);
209 
211 }
212 /*
213 
214 ./buck-out/gen/folly/synchronization/test/parking_lot_test --benchmark
215 --bm_min_iters=10000 --threads=4
216 ============================================================================
217 folly/synchronization/test/ParkingLotBenchmark.cpprelative time/iter iters/s
218 ============================================================================
219 FutexNoWaitersWake 163.43ns 6.12M
220 ParkingLotNoWaitersWake 29.64% 551.43ns 1.81M
221 FutexWakeOne 156.78ns 6.38M
222 ParkingLotWakeOne 37.49% 418.21ns 2.39M
223 FutexWakeAll 1.82us 549.52K
224 ParkingLotWakeAll 449.63% 404.73ns 2.47M
225 ============================================================================
226 
227 ./buck-out/gen/folly/synchronization/test/parking_lot_test --benchmark
228 --bm_min_iters=10000 --threads=32
229 ============================================================================
230 folly/synchronization/test/ParkingLotBenchmark.cpprelative time/iter iters/s
231 ============================================================================
232 FutexNoWaitersWake 379.59ns 2.63M
233 ParkingLotNoWaitersWake 7.94% 4.78us 209.08K
234 FutexWakeOne 163.59ns 6.11M
235 ParkingLotWakeOne 6.41% 2.55us 392.07K
236 FutexWakeAll 12.46us 80.27K
237 ParkingLotWakeAll 784.76% 1.59us 629.92K
238 ============================================================================ */
auto f
char b
void unpark(const Key key, Unparker &&func)
Atom< std::uint32_t > Futex
Definition: Futex.h:51
ParkingLot lot
ParkResult park(const Key key, D &&data, ToPark &&toPark, PreWait &&preWait)
Definition: ParkingLot.h:189
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
void runBenchmarks()
Definition: Benchmark.cpp:456
int main(int argc, char **argv)
FutexResult futexWait(const Futex *futex, uint32_t expected, uint32_t waitMask)
Definition: Futex-inl.h:100
BENCHMARK_RELATIVE(ParkingLotNoWaitersWake, iters)
std::vector< std::thread::id > threads
char ** argv
BENCHMARK(fbFollyGlobalBenchmarkBaseline)
Definition: Benchmark.cpp:84
DEFINE_uint64(threads, 32,"Number of threads for benchmark")
int futexWake(const Futex *futex, int count, uint32_t wakeMask)
Definition: Futex-inl.h:107