proxygen
ExceptionWrapperBenchmark.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-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 <folly/ExceptionWrapper.h>
17 
18 #include <atomic>
19 #include <exception>
20 #include <stdexcept>
21 #include <thread>
22 #include <vector>
23 
24 #include <folly/Benchmark.h>
26 
28  num_threads,
29  32,
30  "Number of threads to run concurrency "
31  "benchmarks");
32 
33 /*
34  * Use case 1: Library wraps errors in either exception_wrapper or
35  * exception_ptr, but user does not care what the exception is after learning
36  * that there is one.
37  */
38 BENCHMARK(exception_ptr_create_and_test, iters) {
39  std::runtime_error e("payload");
40  for (size_t i = 0; i < iters; ++i) {
41  auto ep = std::make_exception_ptr(e);
42  bool b = static_cast<bool>(ep);
44  }
45 }
46 
47 BENCHMARK_RELATIVE(exception_wrapper_create_and_test, iters) {
48  std::runtime_error e("payload");
49  for (size_t i = 0; i < iters; ++i) {
50  auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
51  bool b = static_cast<bool>(ew);
53  }
54 }
55 
57 
58 BENCHMARK(exception_ptr_create_and_test_concurrent, iters) {
59  std::atomic<bool> go(false);
60  std::vector<std::thread> threads;
62  for (int t = 0; t < FLAGS_num_threads; ++t) {
63  threads.emplace_back([&go, iters] {
64  while (!go) {
65  }
66  std::runtime_error e("payload");
67  for (size_t i = 0; i < iters; ++i) {
68  auto ep = std::make_exception_ptr(e);
69  bool b = static_cast<bool>(ep);
71  }
72  });
73  }
74  }
75  go.store(true);
76  for (auto& t : threads) {
77  t.join();
78  }
79 }
80 
81 BENCHMARK_RELATIVE(exception_wrapper_create_and_test_concurrent, iters) {
82  std::atomic<bool> go(false);
83  std::vector<std::thread> threads;
85  for (int t = 0; t < FLAGS_num_threads; ++t) {
86  threads.emplace_back([&go, iters] {
87  while (!go) {
88  }
89  std::runtime_error e("payload");
90  for (size_t i = 0; i < iters; ++i) {
91  auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
92  bool b = static_cast<bool>(ew);
94  }
95  });
96  }
97  }
98  go.store(true);
99  for (auto& t : threads) {
100  t.join();
101  }
102 }
103 
105 
106 /*
107  * Use case 2: Library wraps errors in either exception_wrapper or
108  * exception_ptr, and user wants to handle std::runtime_error. This can be done
109  * either by rehtrowing or with dynamic_cast.
110  */
111 BENCHMARK(exception_ptr_create_and_throw, iters) {
112  std::runtime_error e("payload");
113  for (size_t i = 0; i < iters; ++i) {
114  auto ep = std::make_exception_ptr(e);
115  try {
116  std::rethrow_exception(ep);
117  } catch (std::runtime_error&) {
118  }
119  }
120 }
121 
122 BENCHMARK_RELATIVE(exception_wrapper_create_and_throw, iters) {
123  std::runtime_error e("payload");
124  for (size_t i = 0; i < iters; ++i) {
125  auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
126  try {
127  ew.throw_exception();
128  } catch (std::runtime_error&) {
129  }
130  }
131 }
132 
133 BENCHMARK_RELATIVE(exception_wrapper_create_and_cast, iters) {
134  std::runtime_error e("payload");
135  for (size_t i = 0; i < iters; ++i) {
136  auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
137  bool b = ew.is_compatible_with<std::runtime_error>();
139  }
140 }
141 
143 
144 BENCHMARK(exception_ptr_create_and_throw_concurrent, iters) {
145  std::atomic<bool> go(false);
146  std::vector<std::thread> threads;
148  for (int t = 0; t < FLAGS_num_threads; ++t) {
149  threads.emplace_back([&go, iters] {
150  while (!go) {
151  }
152  std::runtime_error e("payload");
153  for (size_t i = 0; i < iters; ++i) {
154  auto ep = std::make_exception_ptr(e);
155  try {
156  std::rethrow_exception(ep);
157  } catch (std::runtime_error&) {
158  }
159  }
160  });
161  }
162  }
163  go.store(true);
164  for (auto& t : threads) {
165  t.join();
166  }
167 }
168 
169 BENCHMARK_RELATIVE(exception_wrapper_create_and_throw_concurrent, iters) {
170  std::atomic<bool> go(false);
171  std::vector<std::thread> threads;
173  for (int t = 0; t < FLAGS_num_threads; ++t) {
174  threads.emplace_back([&go, iters] {
175  while (!go) {
176  }
177  std::runtime_error e("payload");
178  for (size_t i = 0; i < iters; ++i) {
179  auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
180  try {
181  ew.throw_exception();
182  } catch (std::runtime_error&) {
183  }
184  }
185  });
186  }
187  }
188  go.store(true);
189  for (auto& t : threads) {
190  t.join();
191  }
192 }
193 
194 BENCHMARK_RELATIVE(exception_wrapper_create_and_cast_concurrent, iters) {
195  std::atomic<bool> go(false);
196  std::vector<std::thread> threads;
198  for (int t = 0; t < FLAGS_num_threads; ++t) {
199  threads.emplace_back([&go, iters] {
200  while (!go) {
201  }
202  std::runtime_error e("payload");
203  for (size_t i = 0; i < iters; ++i) {
204  auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
205  bool b = ew.is_compatible_with<std::runtime_error>();
207  }
208  });
209  }
210  }
211  go.store(true);
212  for (auto& t : threads) {
213  t.join();
214  }
215 }
216 
217 int main(int argc, char* argv[]) {
218  gflags::ParseCommandLineFlags(&argc, &argv, true);
220  return 0;
221 }
222 
223 /*
224 _bin/folly/test/exception_wrapper_benchmark --bm_min_iters=100000
225 ============================================================================
226 folly/test/ExceptionWrapperBenchmark.cpp relative time/iter iters/s
227 ============================================================================
228 exception_ptr_create_and_test 2.03us 492.88K
229 exception_wrapper_create_and_test 2542.59% 79.80ns 12.53M
230 ----------------------------------------------------------------------------
231 exception_ptr_create_and_test_concurrent 162.39us 6.16K
232 exception_wrapper_create_and_test_concurrent 95847.91% 169.43ns 5.90M
233 ----------------------------------------------------------------------------
234 exception_ptr_create_and_throw 4.24us 236.06K
235 exception_wrapper_create_and_throw 141.15% 3.00us 333.20K
236 exception_wrapper_create_and_cast 5321.54% 79.61ns 12.56M
237 ----------------------------------------------------------------------------
238 exception_ptr_create_and_throw_concurrent 330.88us 3.02K
239 exception_wrapper_create_and_throw_concurrent 143.66% 230.32us 4.34K
240 exception_wrapper_create_and_cast_concurrent 194828.54% 169.83ns 5.89M
241 ============================================================================
242 */
BENCHMARK(exception_ptr_create_and_test, iters)
BENCHMARK_RELATIVE(exception_wrapper_create_and_test, iters)
char b
#define BENCHMARK_SUSPEND
Definition: Benchmark.h:576
void runBenchmarks()
Definition: Benchmark.cpp:456
int main(int argc, char *argv[])
std::vector< std::thread::id > threads
DEFINE_int32(num_threads, 32,"Number of threads to run concurrency ""benchmarks")
char ** argv
auto doNotOptimizeAway(const T &datum) -> typename std::enable_if< !detail::DoNotOptimizeAwayNeedsIndirect< T >::value >::type
Definition: Benchmark.h:258
BENCHMARK_DRAW_LINE()