2 * Copyright 2014 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.
16 #include <folly/ExceptionWrapper.h>
18 #include <gflags/gflags.h>
25 #include <folly/Benchmark.h>
27 DEFINE_int32(num_threads, 32, "Number of threads to run concurrency "
31 * Use case 1: Library wraps errors in either exception_wrapper or
32 * exception_ptr, but user does not care what the exception is after learning
35 BENCHMARK(exception_ptr_create_and_test, iters) {
36 std::runtime_error e("payload");
37 for (int i = 0; i < iters; ++i) {
38 auto ep = std::make_exception_ptr(e);
43 BENCHMARK_RELATIVE(exception_wrapper_create_and_test, iters) {
44 std::runtime_error e("payload");
45 for (int i = 0; i < iters; ++i) {
46 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
53 BENCHMARK(exception_ptr_create_and_test_concurrent, iters) {
54 std::atomic<bool> go(false);
55 std::vector<std::thread> threads;
57 for (int t = 0; t < FLAGS_num_threads; ++t) {
58 threads.emplace_back([&go, iters] {
60 std::runtime_error e("payload");
61 for (int i = 0; i < iters; ++i) {
62 auto ep = std::make_exception_ptr(e);
69 for (auto& t : threads) {
74 BENCHMARK_RELATIVE(exception_wrapper_create_and_test_concurrent, iters) {
75 std::atomic<bool> go(false);
76 std::vector<std::thread> threads;
78 for (int t = 0; t < FLAGS_num_threads; ++t) {
79 threads.emplace_back([&go, iters] {
81 std::runtime_error e("payload");
82 for (int i = 0; i < iters; ++i) {
83 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
90 for (auto& t : threads) {
98 * Use case 2: Library wraps errors in either exception_wrapper or
99 * exception_ptr, and user wants to handle std::runtime_error. This can be done
100 * either by rehtrowing or with dynamic_cast.
102 BENCHMARK(exception_ptr_create_and_throw, iters) {
103 std::runtime_error e("payload");
104 for (int i = 0; i < iters; ++i) {
105 auto ep = std::make_exception_ptr(e);
107 std::rethrow_exception(ep);
109 } catch (std::runtime_error& e) {
114 BENCHMARK_RELATIVE(exception_wrapper_create_and_throw, iters) {
115 std::runtime_error e("payload");
116 for (int i = 0; i < iters; ++i) {
117 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
121 } catch (std::runtime_error& e) {
126 BENCHMARK_RELATIVE(exception_wrapper_create_and_cast, iters) {
127 std::runtime_error e("payload");
128 for (int i = 0; i < iters; ++i) {
129 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
130 std::exception* basePtr = static_cast<std::exception*>(ew.get());
131 auto ep = dynamic_cast<std::runtime_error*>(basePtr);
137 BENCHMARK_DRAW_LINE()
139 BENCHMARK(exception_ptr_create_and_throw_concurrent, iters) {
140 std::atomic<bool> go(false);
141 std::vector<std::thread> threads;
143 for (int t = 0; t < FLAGS_num_threads; ++t) {
144 threads.emplace_back([&go, iters] {
146 std::runtime_error e("payload");
147 for (int i = 0; i < iters; ++i) {
148 auto ep = std::make_exception_ptr(e);
150 std::rethrow_exception(ep);
152 } catch (std::runtime_error& e) {
159 for (auto& t : threads) {
164 BENCHMARK_RELATIVE(exception_wrapper_create_and_throw_concurrent, iters) {
165 std::atomic<bool> go(false);
166 std::vector<std::thread> threads;
168 for (int t = 0; t < FLAGS_num_threads; ++t) {
169 threads.emplace_back([&go, iters] {
171 std::runtime_error e("payload");
172 for (int i = 0; i < iters; ++i) {
173 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
177 } catch (std::runtime_error& e) {
184 for (auto& t : threads) {
189 BENCHMARK_RELATIVE(exception_wrapper_create_and_cast_concurrent, iters) {
190 std::atomic<bool> go(false);
191 std::vector<std::thread> threads;
193 for (int t = 0; t < FLAGS_num_threads; ++t) {
194 threads.emplace_back([&go, iters] {
196 std::runtime_error e("payload");
197 for (int i = 0; i < iters; ++i) {
198 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
199 std::exception* basePtr = static_cast<std::exception*>(ew.get());
200 auto ep = dynamic_cast<std::runtime_error*>(basePtr);
207 for (auto& t : threads) {
212 int main(int argc, char *argv[]) {
213 gflags::ParseCommandLineFlags(&argc, &argv, true);
214 folly::runBenchmarks();
219 _bin/folly/test/exception_wrapper_benchmark --bm_min_iters=100000
220 ============================================================================
221 folly/test/ExceptionWrapperBenchmark.cpp relative time/iter iters/s
222 ============================================================================
223 exception_ptr_create_and_test 2.03us 492.88K
224 exception_wrapper_create_and_test 2542.59% 79.80ns 12.53M
225 ----------------------------------------------------------------------------
226 exception_ptr_create_and_test_concurrent 162.39us 6.16K
227 exception_wrapper_create_and_test_concurrent 95847.91% 169.43ns 5.90M
228 ----------------------------------------------------------------------------
229 exception_ptr_create_and_throw 4.24us 236.06K
230 exception_wrapper_create_and_throw 141.15% 3.00us 333.20K
231 exception_wrapper_create_and_cast 5321.54% 79.61ns 12.56M
232 ----------------------------------------------------------------------------
233 exception_ptr_create_and_throw_concurrent 330.88us 3.02K
234 exception_wrapper_create_and_throw_concurrent 143.66% 230.32us 4.34K
235 exception_wrapper_create_and_cast_concurrent 194828.54% 169.83ns 5.89M
236 ============================================================================