ExceptionWrapperBenchmark.cpp 7.2 KB

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