mirror of
https://github.com/boostorg/beast.git
synced 2025-08-01 22:04:34 +02:00
Remove BodyReader::is_deferred (API Change):
The is_deferred nested type is removed from the BodyReader requirements. Performance for sending messages with `file_body` was cut almost in half with is_deferred as `std::true_type` since it caused double the number of socket writes. If the deferred behavior is absolutely necessary, callers can get the same effect by manually sending the headers first. Actions Required: * Callers who need the behavior of is_deferred as `std::true_type` should manually construct a serializer and serialize the header first, followed by the body.
This commit is contained in:
@@ -3,6 +3,7 @@ Version 68:
|
|||||||
API Changes:
|
API Changes:
|
||||||
|
|
||||||
* Change BodyReader, BodyWriter requirements
|
* Change BodyReader, BodyWriter requirements
|
||||||
|
* Remove BodyReader::is_deferred
|
||||||
|
|
||||||
Actions Required:
|
Actions Required:
|
||||||
|
|
||||||
|
@@ -45,22 +45,6 @@ In this table:
|
|||||||
A type which meets the requirements of __ConstBufferSequence__.
|
A type which meets the requirements of __ConstBufferSequence__.
|
||||||
This is the type of buffer returned by `X::get`.
|
This is the type of buffer returned by `X::get`.
|
||||||
]
|
]
|
||||||
][
|
|
||||||
[`X::is_deferred`]
|
|
||||||
[]
|
|
||||||
[
|
|
||||||
The type `std::true_type` if the serialization implementation
|
|
||||||
should only attempt to retrieve buffers from the reader after
|
|
||||||
the header has been serialized. Otherwise, if this type is
|
|
||||||
`std::false_type` the implementation will activate an
|
|
||||||
optimization: the first buffer produced during serialization
|
|
||||||
will contain both the header and some or all of this body.
|
|
||||||
|
|
||||||
Implementations of [*BodyReader] for which initialization is
|
|
||||||
expensive, should use `std::false_type` here, to reduce the
|
|
||||||
latency experienced by the remote host when expecting to read
|
|
||||||
the HTTP header.
|
|
||||||
]
|
|
||||||
][
|
][
|
||||||
[`X(m,ec);`]
|
[`X(m,ec);`]
|
||||||
[]
|
[]
|
||||||
|
@@ -98,14 +98,6 @@ class file_body::reader
|
|||||||
char buf_[4096]; // Small buffer for reading
|
char buf_[4096]; // Small buffer for reading
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// This nested type informs the serializer that it should
|
|
||||||
// wait until after sending the header to initialize the
|
|
||||||
// reader. We set this to true, otherwise opening the file
|
|
||||||
// during `init` could introduce latency which delays
|
|
||||||
// the remote endpoint from receiving the header quickly.
|
|
||||||
//
|
|
||||||
using is_deferred = std::true_type;
|
|
||||||
|
|
||||||
// The type of buffer sequence returned by `get`.
|
// The type of buffer sequence returned by `get`.
|
||||||
//
|
//
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
@@ -113,8 +105,6 @@ public:
|
|||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
//
|
//
|
||||||
// This is called after the header is serialized, because
|
|
||||||
// we declared `is_deferred` to be `std::true_type`.
|
|
||||||
// `m` holds the message we are sending, which will
|
// `m` holds the message we are sending, which will
|
||||||
// always have the `file_body` as the body type.
|
// always have the `file_body` as the body type.
|
||||||
//
|
//
|
||||||
|
@@ -96,8 +96,6 @@ struct buffer_body
|
|||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffers_1;
|
||||||
|
|
||||||
|
@@ -45,8 +45,6 @@ struct basic_dynamic_body
|
|||||||
DynamicBuffer const& body_;
|
DynamicBuffer const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
typename DynamicBuffer::const_buffers_type;
|
typename DynamicBuffer::const_buffers_type;
|
||||||
|
|
||||||
|
@@ -49,8 +49,6 @@ struct empty_body
|
|||||||
#else
|
#else
|
||||||
struct reader
|
struct reader
|
||||||
{
|
{
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::null_buffers;
|
boost::asio::null_buffers;
|
||||||
|
|
||||||
|
@@ -74,12 +74,10 @@ get(error_code& ec, Visit&& visit)
|
|||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
auto result = rd_->get(ec);
|
auto result = rd_->get(ec);
|
||||||
|
if(ec == error::need_more)
|
||||||
|
goto go_header_only;
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
|
||||||
// Can't use need_more when ! is_deferred
|
|
||||||
BOOST_ASSERT(ec != error::need_more);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if(! result)
|
if(! result)
|
||||||
goto go_header_only;
|
goto go_header_only;
|
||||||
more_ = result->second;
|
more_ = result->second;
|
||||||
@@ -103,10 +101,12 @@ get(error_code& ec, Visit&& visit)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case do_body:
|
case do_body:
|
||||||
BOOST_ASSERT(! rd_);
|
if(! rd_)
|
||||||
rd_.emplace(m_, ec);
|
{
|
||||||
if(ec)
|
rd_.emplace(m_, ec);
|
||||||
return;
|
if(ec)
|
||||||
|
return;
|
||||||
|
}
|
||||||
s_ = do_body + 1;
|
s_ = do_body + 1;
|
||||||
BOOST_FALLTHROUGH;
|
BOOST_FALLTHROUGH;
|
||||||
|
|
||||||
@@ -139,12 +139,10 @@ get(error_code& ec, Visit&& visit)
|
|||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
auto result = rd_->get(ec);
|
auto result = rd_->get(ec);
|
||||||
|
if(ec == error::need_more)
|
||||||
|
goto go_header_only_c;
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
|
||||||
// Can't use need_more when ! is_deferred
|
|
||||||
BOOST_ASSERT(ec != error::need_more);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if(! result)
|
if(! result)
|
||||||
goto go_header_only_c;
|
goto go_header_only_c;
|
||||||
more_ = result->second;
|
more_ = result->second;
|
||||||
@@ -179,10 +177,12 @@ get(error_code& ec, Visit&& visit)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case do_body_c:
|
case do_body_c:
|
||||||
BOOST_ASSERT(! rd_);
|
if(! rd_)
|
||||||
rd_.emplace(m_, ec);
|
{
|
||||||
if(ec)
|
rd_.emplace(m_, ec);
|
||||||
return;
|
if(ec)
|
||||||
|
return;
|
||||||
|
}
|
||||||
s_ = do_body_c + 1;
|
s_ = do_body_c + 1;
|
||||||
BOOST_FALLTHROUGH;
|
BOOST_FALLTHROUGH;
|
||||||
|
|
||||||
|
@@ -144,16 +144,11 @@ class serializer
|
|||||||
do_complete = 110
|
do_complete = 110
|
||||||
};
|
};
|
||||||
|
|
||||||
void split(bool, std::true_type) {}
|
|
||||||
void split(bool v, std::false_type) { split_ = v; }
|
|
||||||
void frdinit(std::true_type);
|
void frdinit(std::true_type);
|
||||||
void frdinit(std::false_type);
|
void frdinit(std::false_type);
|
||||||
|
|
||||||
using reader = typename Body::reader;
|
using reader = typename Body::reader;
|
||||||
|
|
||||||
using is_deferred =
|
|
||||||
typename reader::is_deferred;
|
|
||||||
|
|
||||||
using ch_t = consuming_buffers<typename
|
using ch_t = consuming_buffers<typename
|
||||||
Fields::reader::const_buffers_type>; // header
|
Fields::reader::const_buffers_type>; // header
|
||||||
|
|
||||||
@@ -190,7 +185,7 @@ class serializer
|
|||||||
boost::variant<boost::blank,
|
boost::variant<boost::blank,
|
||||||
ch_t, cb0_t, cb1_t, ch0_t, ch1_t, ch2_t> v_;
|
ch_t, cb0_t, cb1_t, ch0_t, ch1_t, ch2_t> v_;
|
||||||
int s_ = do_construct;
|
int s_ = do_construct;
|
||||||
bool split_ = is_deferred::value;
|
bool split_ = false;
|
||||||
bool header_done_ = false;
|
bool header_done_ = false;
|
||||||
bool chunked_;
|
bool chunked_;
|
||||||
bool close_;
|
bool close_;
|
||||||
@@ -227,14 +222,12 @@ public:
|
|||||||
When the split feature is enabled, the implementation will
|
When the split feature is enabled, the implementation will
|
||||||
write only the octets corresponding to the serialized header
|
write only the octets corresponding to the serialized header
|
||||||
first. If the header has already been written, this function
|
first. If the header has already been written, this function
|
||||||
will have no effect on output. This function should be called
|
will have no effect on output.
|
||||||
before retrieving any buffers using @ref get, otherwise the
|
|
||||||
behavior is undefined.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
split(bool v)
|
split(bool v)
|
||||||
{
|
{
|
||||||
split(v, is_deferred{});
|
split_ = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return `true` if serialization of the header is complete.
|
/** Return `true` if serialization of the header is complete.
|
||||||
|
@@ -47,8 +47,6 @@ struct string_body
|
|||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffers_1;
|
||||||
|
|
||||||
|
@@ -48,8 +48,6 @@ struct string_view_body
|
|||||||
string_view body_;
|
string_view body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffers_1;
|
||||||
|
|
||||||
|
@@ -48,14 +48,6 @@ struct Body_BodyReader {
|
|||||||
struct BodyReader
|
struct BodyReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Controls when the implementation requests buffers.
|
|
||||||
|
|
||||||
If false, the implementation will request the first buffer
|
|
||||||
immediately and try to serialize both the header and some
|
|
||||||
or all of the body in a single buffer.
|
|
||||||
*/
|
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
/// The type of buffer returned by `get`.
|
/// The type of buffer returned by `get`.
|
||||||
using const_buffers_type = boost::asio::const_buffers_1;
|
using const_buffers_type = boost::asio::const_buffers_1;
|
||||||
|
|
||||||
|
@@ -42,8 +42,6 @@ public:
|
|||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffers_1;
|
||||||
|
|
||||||
@@ -67,7 +65,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<
|
template<
|
||||||
bool isDeferred,
|
|
||||||
bool isSplit,
|
bool isSplit,
|
||||||
bool isFinalEmpty
|
bool isFinalEmpty
|
||||||
>
|
>
|
||||||
@@ -85,9 +82,6 @@ public:
|
|||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using is_deferred =
|
|
||||||
std::integral_constant<bool, isDeferred>;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffers_1;
|
||||||
|
|
||||||
@@ -220,8 +214,6 @@ public:
|
|||||||
value_type const& body_;
|
value_type const& body_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using is_deferred = std::false_type;
|
|
||||||
|
|
||||||
using const_buffers_type =
|
using const_buffers_type =
|
||||||
boost::asio::const_buffers_1;
|
boost::asio::const_buffers_1;
|
||||||
|
|
||||||
@@ -844,14 +836,10 @@ public:
|
|||||||
yield_to(
|
yield_to(
|
||||||
[&](yield_context yield)
|
[&](yield_context yield)
|
||||||
{
|
{
|
||||||
testWriteStream<test_body<false, false, false>>(yield);
|
testWriteStream<test_body<false, false>>(yield);
|
||||||
testWriteStream<test_body<false, false, true>>(yield);
|
testWriteStream<test_body<false, true>>(yield);
|
||||||
testWriteStream<test_body<false, true, false>>(yield);
|
testWriteStream<test_body< true, false>>(yield);
|
||||||
testWriteStream<test_body<false, true, true>>(yield);
|
testWriteStream<test_body< true, true>>(yield);
|
||||||
testWriteStream<test_body< true, false, false>>(yield);
|
|
||||||
testWriteStream<test_body< true, false, true>>(yield);
|
|
||||||
testWriteStream<test_body< true, true, false>>(yield);
|
|
||||||
testWriteStream<test_body< true, true, true>>(yield);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user