Serialize in one step when possible

fix #546
This commit is contained in:
Vinnie Falco
2017-06-26 18:26:35 -07:00
parent d45682cfcd
commit 7abe6f6e09
5 changed files with 167 additions and 51 deletions

View File

@ -36,7 +36,7 @@ matrix:
# gcc coverage
- compiler: gcc
env:
- GCC_VER=5
- GCC_VER=6
- VARIANT=coverage
- ADDRESS_MODEL=64
- DO_VALGRIND=false
@ -45,8 +45,8 @@ matrix:
addons:
apt:
packages:
- gcc-5
- g++-5
- gcc-6
- g++-6
- libssl-dev
- *base_packages
sources:
@ -71,7 +71,7 @@ matrix:
# later GCC
- compiler: gcc
env:
- GCC_VER=6
- GCC_VER=5
- VARIANT=release
- DO_VALGRIND=true
- ADDRESS_MODEL=64
@ -80,8 +80,8 @@ matrix:
addons:
apt:
packages:
- gcc-6
- g++-6
- gcc-5
- g++-5
- libssl-dev
- *base_packages
sources:
@ -109,39 +109,6 @@ matrix:
sources:
- *base_sources
# Clang/UndefinedBehaviourSanitizer
#- compiler: clang
# env:
# - GCC_VER=4.8
# - VARIANT=usan
# - CLANG_VER=3.8
# - ADDRESS_MODEL=64
# - UBSAN_OPTIONS='print_stacktrace=1'
# - BUILD_SYSTEM=cmake
# - PATH=$PWD/cmake/bin:$PATH
# - PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
# addons:
# apt:
# packages:
# - *base_packages
# sources:
# - *base_sources
# Clang/AddressSanitizer
#- compiler: clang
# env:
# - GCC_VER=5
# - VARIANT=asan
# - CLANG_VER=3.8
# - ADDRESS_MODEL=64
# - PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
# addons:
# apt:
# packages:
# - *base_packages
# sources:
# - *base_sources
cache:
directories:
- $BOOST_ROOT

View File

@ -1,3 +1,9 @@
Version 70:
* Serialize in one step when possible
--------------------------------------------------------------------------------
Version 69:
* basic_parser optimizations

View File

@ -146,6 +146,38 @@ get(error_code& ec, Visit&& visit)
if(! result)
goto go_header_only_c;
more_ = result->second;
#if ! BEAST_NO_BIG_VARIANTS
if(! more_)
{
// do it all in one buffer
v_ = ch3_t{
boost::in_place_init,
frd_->get(),
detail::chunk_header{
buffer_size(result->first)},
[&]()
{
auto sv = d_(result->first);
return boost::asio::const_buffers_1{
sv.data(), sv.size()};
}(),
detail::chunk_crlf(),
result->first,
detail::chunk_crlf(),
detail::chunk_final(),
[&]()
{
auto sv = d_(
boost::asio::null_buffers{});
return boost::asio::const_buffers_1{
sv.data(), sv.size()};
}(),
detail::chunk_crlf()};
goto go_all_c;
}
#endif
v_ = ch0_t{
boost::in_place_init,
frd_->get(),
@ -194,6 +226,37 @@ get(error_code& ec, Visit&& visit)
if(! result)
goto go_final_c;
more_ = result->second;
#if ! BEAST_NO_BIG_VARIANTS
if(! more_)
{
// do it all in one buffer
v_ = ch2_t{
boost::in_place_init,
detail::chunk_header{
buffer_size(result->first)},
[&]()
{
auto sv = d_(result->first);
return boost::asio::const_buffers_1{
sv.data(), sv.size()};
}(),
detail::chunk_crlf(),
result->first,
detail::chunk_crlf(),
detail::chunk_final(),
[&]()
{
auto sv = d_(
boost::asio::null_buffers{});
return boost::asio::const_buffers_1{
sv.data(), sv.size()};
}(),
detail::chunk_crlf()};
goto go_body_final_c;
}
#endif
v_ = ch1_t{
boost::in_place_init,
detail::chunk_header{
@ -216,9 +279,23 @@ get(error_code& ec, Visit&& visit)
visit(ec, boost::get<ch1_t>(v_));
break;
go_final_c:
#if ! BEAST_NO_BIG_VARIANTS
go_body_final_c:
s_ = do_body_final_c;
case do_body_final_c:
visit(ec, boost::get<ch2_t>(v_));
break;
go_all_c:
s_ = do_all_c;
case do_all_c:
visit(ec, boost::get<ch3_t>(v_));
break;
#endif
go_final_c:
case do_final_c:
v_ = ch2_t{
v_ = ch4_t{
boost::in_place_init,
detail::chunk_final(),
[&]()
@ -234,7 +311,7 @@ get(error_code& ec, Visit&& visit)
BEAST_FALLTHROUGH;
case do_final_c + 1:
visit(ec, boost::get<ch2_t>(v_));
visit(ec, boost::get<ch4_t>(v_));
break;
//----------------------------------------------------------------------
@ -346,11 +423,38 @@ consume(std::size_t n)
s_ = do_final_c;
break;
#if ! BEAST_NO_BIG_VARIANTS
case do_body_final_c:
{
auto& b = boost::get<ch2_t>(v_);
BOOST_ASSERT(n <= buffer_size(b));
b.consume(n);
if(buffer_size(b) > 0)
break;
v_ = boost::blank{};
s_ = do_complete;
break;
}
case do_all_c:
{
auto& b = boost::get<ch3_t>(v_);
BOOST_ASSERT(n <= buffer_size(b));
b.consume(n);
if(buffer_size(b) > 0)
break;
header_done_ = true;
v_ = boost::blank{};
s_ = do_complete;
break;
}
#endif
case do_final_c + 1:
BOOST_ASSERT(buffer_size(
boost::get<ch2_t>(v_)));
boost::get<ch2_t>(v_).consume(n);
if(buffer_size(boost::get<ch2_t>(v_)) > 0)
boost::get<ch4_t>(v_)));
boost::get<ch4_t>(v_).consume(n);
if(buffer_size(boost::get<ch4_t>(v_)) > 0)
break;
v_ = boost::blank{};
goto go_complete;

View File

@ -19,6 +19,14 @@
#include <boost/optional.hpp>
#include <boost/variant.hpp>
#ifndef BEAST_NO_BIG_VARIANTS
# if defined(BOOST_GCC) && BOOST_GCC < 50000 && BOOST_VERSION < 106400
# define BEAST_NO_BIG_VARIANTS 1
# else
# define BEAST_NO_BIG_VARIANTS 0
# endif
#endif
namespace beast {
namespace http {
@ -138,10 +146,14 @@ class serializer
do_init_c = 50,
do_header_only_c = 60,
do_header_c = 70,
do_body_c = 90,
do_final_c = 100,
do_body_c = 80,
do_final_c = 90,
#if ! BEAST_NO_BIG_VARIANTS
do_body_final_c = 100,
do_all_c = 110,
#endif
do_complete = 110
do_complete = 120
};
void frdinit(std::true_type);
@ -166,7 +178,7 @@ class serializer
boost::asio::const_buffers_1, // crlf
typename reader::const_buffers_type, // body
boost::asio::const_buffers_1>>; // crlf
using ch1_t = consuming_buffers<buffer_cat_view<
detail::chunk_header, // chunk-header
boost::asio::const_buffers_1, // chunk-ext
@ -174,7 +186,30 @@ class serializer
typename reader::const_buffers_type, // body
boost::asio::const_buffers_1>>; // crlf
#if ! BEAST_NO_BIG_VARIANTS
using ch2_t = consuming_buffers<buffer_cat_view<
detail::chunk_header, // chunk-header
boost::asio::const_buffers_1, // chunk-ext
boost::asio::const_buffers_1, // crlf
typename reader::const_buffers_type, // body
boost::asio::const_buffers_1, // crlf
boost::asio::const_buffers_1, // chunk-final
boost::asio::const_buffers_1, // trailers
boost::asio::const_buffers_1>>; // crlf
using ch3_t = consuming_buffers<buffer_cat_view<
typename Fields::reader::const_buffers_type,// header
detail::chunk_header, // chunk-header
boost::asio::const_buffers_1, // chunk-ext
boost::asio::const_buffers_1, // crlf
typename reader::const_buffers_type, // body
boost::asio::const_buffers_1, // crlf
boost::asio::const_buffers_1, // chunk-final
boost::asio::const_buffers_1, // trailers
boost::asio::const_buffers_1>>; // crlf
#endif
using ch4_t = consuming_buffers<buffer_cat_view<
boost::asio::const_buffers_1, // chunk-final
boost::asio::const_buffers_1, // trailers
boost::asio::const_buffers_1>>; // crlf
@ -183,7 +218,11 @@ class serializer
boost::optional<typename Fields::reader> frd_;
boost::optional<reader> rd_;
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
#if ! BEAST_NO_BIG_VARIANTS
,ch2_t, ch3_t
#endif
, ch4_t> v_;
int s_ = do_construct;
bool split_ = false;
bool header_done_ = false;

View File

@ -34,7 +34,7 @@ if [[ ! -x cmake/bin/cmake && -d cmake ]]; then
rm -fr cmake
fi
if [[ ! -d cmake && ${BUILD_SYSTEM:-} == cmake ]]; then
CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.8.0-Linux-x86_64.tar.gz"
CMAKE_URL="http://www.cmake.org/files/v3.8/cmake-3.8.0-Linux-x86_64.tar.gz"
mkdir cmake && wget --no-check-certificate -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
fi