2 * Copyright 2016 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>
24 #include <folly/Benchmark.h>
25 #include <folly/portability/GFlags.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 (size_t 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 (size_t 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 (size_t 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 (size_t 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 (size_t i = 0; i < iters; ++i) {
105 auto ep = std::make_exception_ptr(e);
107 std::rethrow_exception(ep);
109 } catch (std::runtime_error&) {
114 BENCHMARK_RELATIVE(exception_wrapper_create_and_throw, iters) {
115 std::runtime_error e("payload");
116 for (size_t i = 0; i < iters; ++i) {
117 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
121 } catch (std::runtime_error&) {
126 BENCHMARK_RELATIVE(exception_wrapper_create_and_cast, iters) {
127 std::runtime_error e("payload");
128 for (size_t i = 0; i < iters; ++i) {
129 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
130 assert(ew.is_compatible_with<std::runtime_error>());
135 BENCHMARK_DRAW_LINE()
137 BENCHMARK(exception_ptr_create_and_throw_concurrent, iters) {
138 std::atomic<bool> go(false);
139 std::vector<std::thread> threads;
141 for (int t = 0; t < FLAGS_num_threads; ++t) {
142 threads.emplace_back([&go, iters] {
144 std::runtime_error e("payload");
145 for (size_t i = 0; i < iters; ++i) {
146 auto ep = std::make_exception_ptr(e);
148 std::rethrow_exception(ep);
150 } catch (std::runtime_error&) {
157 for (auto& t : threads) {
162 BENCHMARK_RELATIVE(exception_wrapper_create_and_throw_concurrent, iters) {
163 std::atomic<bool> go(false);
164 std::vector<std::thread> threads;
166 for (int t = 0; t < FLAGS_num_threads; ++t) {
167 threads.emplace_back([&go, iters] {
169 std::runtime_error e("payload");
170 for (size_t i = 0; i < iters; ++i) {
171 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
175 } catch (std::runtime_error&) {
182 for (auto& t : threads) {
187 BENCHMARK_RELATIVE(exception_wrapper_create_and_cast_concurrent, iters) {
188 std::atomic<bool> go(false);
189 std::vector<std::thread> threads;
191 for (int t = 0; t < FLAGS_num_threads; ++t) {
192 threads.emplace_back([&go, iters] {
194 std::runtime_error e("payload");
195 for (size_t i = 0; i < iters; ++i) {
196 auto ew = folly::make_exception_wrapper<std::runtime_error>(e);
197 assert(ew.is_compatible_with<std::runtime_error>());
203 for (auto& t : threads) {
208 int main(int argc, char *argv[]) {
209 gflags::ParseCommandLineFlags(&argc, &argv, true);
210 folly::runBenchmarks();
215 _bin/folly/test/exception_wrapper_benchmark --bm_min_iters=100000
216 ============================================================================
217 folly/test/ExceptionWrapperBenchmark.cpp relative time/iter iters/s
218 ============================================================================
219 exception_ptr_create_and_test 2.03us 492.88K
220 exception_wrapper_create_and_test 2542.59% 79.80ns 12.53M
221 ----------------------------------------------------------------------------
222 exception_ptr_create_and_test_concurrent 162.39us 6.16K
223 exception_wrapper_create_and_test_concurrent 95847.91% 169.43ns 5.90M
224 ----------------------------------------------------------------------------
225 exception_ptr_create_and_throw 4.24us 236.06K
226 exception_wrapper_create_and_throw 141.15% 3.00us 333.20K
227 exception_wrapper_create_and_cast 5321.54% 79.61ns 12.56M
228 ----------------------------------------------------------------------------
229 exception_ptr_create_and_throw_concurrent 330.88us 3.02K
230 exception_wrapper_create_and_throw_concurrent 143.66% 230.32us 4.34K
231 exception_wrapper_create_and_cast_concurrent 194828.54% 169.83ns 5.89M
232 ============================================================================