From ac47a21ded01162bc880745f42cd6b3381a9f7e8 Mon Sep 17 00:00:00 2001 From: Pavel Melkozerov Date: Fri, 21 Feb 2025 11:50:45 +0300 Subject: [PATCH] test: Add direct exception passing for awaits for perf test Added direct exception passing case for coroutines. Exception are are passed directly after awaited future has been resolved with return_exception_ptr. This option can be a balance between of need frequent exception passing and convenience of using coroutines. The limitations of a such usage the return_exception_ptr cannot be used with void futures. test iterations median mad min max allocs tasks inst cycles chain.then_value 31708032 31.415ns 0.177ns 31.175ns 31.592ns 1.031 1.062 320.1 118.6 chain.await_value 20403392 49.203ns 0.048ns 48.914ns 49.260ns 1.063 1.094 456.9 186.1 chain.await_value_as_future 18967008 52.973ns 0.090ns 52.548ns 53.483ns 1.063 1.094 482.4 201.0 chain.then_exception 30921504 32.120ns 0.147ns 31.962ns 33.095ns 1.063 1.062 321.2 122.3 chain.await_exception 504704 1.975us 9.888ns 1.966us 1.989us 2.125 1.094 24397.8 7498.7 chain.await_exception_as_future 17931328 56.013ns 0.127ns 55.839ns 56.301ns 1.094 1.094 546.2 212.3 Closes scylladb/seastar#2653 --- tests/perf/future_util_perf.cc | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/perf/future_util_perf.cc b/tests/perf/future_util_perf.cc index d02d25a26a..27e2abf591 100644 --- a/tests/perf/future_util_perf.cc +++ b/tests/perf/future_util_perf.cc @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -82,6 +83,25 @@ struct chain { co_await std::move(w); } } + + [[gnu::noinline]] + future do_await_as_future(future w, int depth = scale) { + if (depth > 0) { + auto fut = co_await coroutine::as_future(do_await_as_future(std::move(w), depth - 1)); + if (fut.failed()) { + co_await seastar::coroutine::return_exception_ptr(fut.get_exception()); + } + value += 1; + perf_tests::do_not_optimize(value); + co_return fut.get(); + } else { + auto fut = co_await coroutine::as_future(std::move(w)); + if (fut.failed()) { + co_await seastar::coroutine::return_exception_ptr(fut.get_exception()); + } + co_return fut.get(); + } + } }; PERF_TEST_F(chain, then_value) @@ -100,6 +120,14 @@ PERF_TEST_F(chain, await_value) return f.then([] { return scale; }); } +PERF_TEST_F(chain, await_value_as_future) +{ + promise p; + auto f = do_await_as_future(p.get_future()); + p.set_value(std::nullopt); + return f.then([](std::nullopt_t) { return scale; }); +} + PERF_TEST_F(chain, then_exception) { promise<> p; @@ -122,6 +150,17 @@ PERF_TEST_F(chain, await_exception) }); } +PERF_TEST_F(chain, await_exception_as_future) +{ + promise p; + auto f = do_await_as_future(p.get_future()); + p.set_exception(std::runtime_error("")); + return f.then_wrapped([] (auto x) { + x.ignore_ready_future(); + return scale; + }); +} + PERF_TEST_F(parallel_for_each, immediate_1) { auto&& begin = range.begin();