Skip to content

Commit 538ab8f

Browse files
committed
Reduces the number of rescheduling needed to process a server sent push.
Performance improved by close to 10%.
1 parent f5f57e3 commit 538ab8f

File tree

5 files changed

+52
-32
lines changed

5 files changed

+52
-32
lines changed

CMakeLists.txt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,16 @@ add_executable(echo_server_client benchmarks/cpp/asio/echo_server_client.cpp)
7979
add_executable(echo_server_direct benchmarks/cpp/asio/echo_server_direct.cpp)
8080

8181
set(tests_cpp17
82-
test_conn_quit
83-
test_conn_tls
84-
test_low_level
85-
test_conn_exec_retry
86-
test_conn_exec_error
87-
test_request
88-
test_run
89-
test_low_level_sync
90-
test_conn_check_health)
82+
test_conn_quit
83+
test_conn_tls
84+
test_low_level
85+
test_conn_exec_retry
86+
test_conn_exec_error
87+
test_request
88+
test_run
89+
test_low_level_sync
90+
test_conn_check_health
91+
)
9192

9293
set(tests_cpp20
9394
test_conn_exec

CMakePresets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"CMAKE_BUILD_TYPE": "Debug",
6767
"CMAKE_CXX_EXTENSIONS": "OFF",
6868
"CMAKE_CXX_FLAGS": "-Wall -Wextra -fsanitize=address",
69-
"CMAKE_CXX_COMPILER": "g++-11",
69+
"CMAKE_CXX_COMPILER": "clang++-13",
7070
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
7171
"CMAKE_CXX_STANDARD_REQUIRED": "ON",
7272
"PROJECT_BINARY_DIR": "${sourceDir}/build/clang++-13",

include/boost/redis/connection_base.hpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace detail {
4343

4444
template <class Conn>
4545
struct wait_receive_op {
46-
Conn* conn;
46+
Conn* conn_;
4747
asio::coroutine coro{};
4848

4949
template <class Self>
@@ -52,14 +52,14 @@ struct wait_receive_op {
5252
{
5353
BOOST_ASIO_CORO_REENTER (coro)
5454
{
55-
BOOST_ASIO_CORO_YIELD
56-
conn->channel_.async_send(system::error_code{}, 0, std::move(self));
57-
BOOST_REDIS_CHECK_OP0(;);
55+
conn_->channel_.cancel();
5856

5957
BOOST_ASIO_CORO_YIELD
60-
conn->channel_.async_send(system::error_code{}, 0, std::move(self));
61-
BOOST_REDIS_CHECK_OP0(;);
62-
58+
conn_->channel_.async_send(system::error_code{}, 0, std::move(self));
59+
if (!conn_->is_open() || is_cancelled(self)) {
60+
self.complete(!!ec ? ec : asio::error::operation_aborted);
61+
return;
62+
}
6363
self.complete({});
6464
}
6565
}
@@ -158,7 +158,7 @@ class read_next_op {
158158

159159
template <class Conn, class Adapter>
160160
struct receive_op {
161-
Conn* conn;
161+
Conn* conn_;
162162
Adapter adapter;
163163
std::size_t read_size = 0;
164164
asio::coroutine coro{};
@@ -171,27 +171,32 @@ struct receive_op {
171171
{
172172
BOOST_ASIO_CORO_REENTER (coro)
173173
{
174-
BOOST_ASIO_CORO_YIELD
175-
conn->channel_.async_receive(std::move(self));
176-
BOOST_REDIS_CHECK_OP1(;);
174+
if (conn_->wait_read_op_notification_) {
175+
BOOST_ASIO_CORO_YIELD
176+
conn_->channel_.async_receive(std::move(self));
177+
if (!conn_->is_open() || is_cancelled(self)) {
178+
self.complete(!!ec ? ec : asio::error::operation_aborted, 0);
179+
return;
180+
}
181+
}
177182

178-
if (conn->use_ssl())
179-
BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn->next_layer(), conn->make_dynamic_buffer(), adapter, std::move(self));
183+
if (conn_->use_ssl())
184+
BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn_->next_layer(), conn_->make_dynamic_buffer(), adapter, std::move(self));
180185
else
181-
BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn->next_layer().next_layer(), conn->make_dynamic_buffer(), adapter, std::move(self));
186+
BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn_->next_layer().next_layer(), conn_->make_dynamic_buffer(), adapter, std::move(self));
182187

183188
if (ec || is_cancelled(self)) {
184-
conn->cancel(operation::run);
185-
conn->cancel(operation::receive);
189+
conn_->cancel(operation::run);
190+
conn_->cancel(operation::receive);
186191
self.complete(!!ec ? ec : asio::error::operation_aborted, {});
187192
return;
188193
}
189194

190195
read_size = n;
191196

192-
BOOST_ASIO_CORO_YIELD
193-
conn->channel_.async_receive(std::move(self));
194-
BOOST_REDIS_CHECK_OP1(;);
197+
conn_->wait_read_op_notification_ = !conn_->is_next_maybe_push();
198+
if (conn_->wait_read_op_notification_)
199+
conn_->channel_.cancel();
195200

196201
self.complete({}, read_size);
197202
return;
@@ -315,6 +320,7 @@ struct run_op {
315320
{
316321
conn->write_buffer_.clear();
317322
conn->read_buffer_.clear();
323+
conn->wait_read_op_notification_ = true;
318324

319325
BOOST_ASIO_CORO_YIELD
320326
asio::experimental::make_parallel_group(
@@ -991,6 +997,11 @@ class connection_base {
991997
stream_->next_layer().close();
992998
}
993999

1000+
bool is_next_maybe_push() const noexcept
1001+
{
1002+
return !read_buffer_.empty() && (resp3::to_type(read_buffer_.front()) == resp3::type::push);
1003+
}
1004+
9941005
auto is_open() const noexcept { return stream_->next_layer().is_open(); }
9951006
auto& lowest_layer() noexcept { return stream_->lowest_layer(); }
9961007

@@ -1009,6 +1020,9 @@ class connection_base {
10091020
std::string write_buffer_;
10101021
reqs_type reqs_;
10111022
std::size_t max_read_size_ = (std::numeric_limits<std::size_t>::max)();
1023+
1024+
// Flag that optimizes reading pushes.
1025+
bool wait_read_op_notification_ = true;
10121026
};
10131027

10141028
} // boost::redis

tests/test_conn_check_health.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define BOOST_TEST_MODULE check-health
1010
#include <boost/test/included/unit_test.hpp>
1111
#include <iostream>
12+
#include <thread>
1213
#include "common.hpp"
1314

1415
namespace net = boost::asio;
@@ -119,5 +120,9 @@ BOOST_AUTO_TEST_CASE(check_health)
119120

120121
BOOST_TEST(!!res1);
121122
BOOST_TEST(!!res2);
123+
124+
// Waits before exiting otherwise it might cause subsequent tests
125+
// to fail.
126+
std::this_thread::sleep_for(std::chrono::seconds{10});
122127
}
123128

tests/test_conn_exec.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(hello_priority)
5151
conn->async_exec(req1, ignore, [&](auto ec, auto){
5252
// Second callback to the called.
5353
std::cout << "req1" << std::endl;
54-
BOOST_TEST(!ec);
54+
BOOST_CHECK_EQUAL(ec, boost::system::error_code{});
5555
BOOST_TEST(!seen2);
5656
BOOST_TEST(seen3);
5757
seen1 = true;
@@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(hello_priority)
6060
conn->async_exec(req2, ignore, [&](auto ec, auto){
6161
// Last callback to the called.
6262
std::cout << "req2" << std::endl;
63-
BOOST_TEST(!ec);
63+
BOOST_CHECK_EQUAL(ec, boost::system::error_code{});
6464
BOOST_TEST(seen1);
6565
BOOST_TEST(seen3);
6666
seen2 = true;
@@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(hello_priority)
7171
conn->async_exec(req3, ignore, [&](auto ec, auto){
7272
// Callback that will be called first.
7373
std::cout << "req3" << std::endl;
74-
BOOST_TEST(!ec);
74+
BOOST_CHECK_EQUAL(ec, boost::system::error_code{});
7575
BOOST_TEST(!seen1);
7676
BOOST_TEST(!seen2);
7777
seen3 = true;

0 commit comments

Comments
 (0)