diff --git a/.travis.yml b/.travis.yml index 17b9ea1c..6a6ab527 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index d44542fc..4962045f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 70: + +* Serialize in one step when possible + +-------------------------------------------------------------------------------- + Version 69: * basic_parser optimizations diff --git a/include/beast/http/impl/serializer.ipp b/include/beast/http/impl/serializer.ipp index 45617d03..ad304b2a 100644 --- a/include/beast/http/impl/serializer.ipp +++ b/include/beast/http/impl/serializer.ipp @@ -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(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(v_)); + break; + + go_all_c: + s_ = do_all_c; + case do_all_c: + visit(ec, boost::get(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(v_)); + visit(ec, boost::get(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(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(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(v_))); - boost::get(v_).consume(n); - if(buffer_size(boost::get(v_)) > 0) + boost::get(v_))); + boost::get(v_).consume(n); + if(buffer_size(boost::get(v_)) > 0) break; v_ = boost::blank{}; goto go_complete; diff --git a/include/beast/http/serializer.hpp b/include/beast/http/serializer.hpp index cbec4304..7a593269 100644 --- a/include/beast/http/serializer.hpp +++ b/include/beast/http/serializer.hpp @@ -19,6 +19,14 @@ #include #include +#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>; // crlf +#if ! BEAST_NO_BIG_VARIANTS using ch2_t = consuming_buffers>; // crlf + + using ch3_t = consuming_buffers>; // crlf +#endif + + using ch4_t = consuming_buffers>; // crlf @@ -183,7 +218,11 @@ class serializer boost::optional frd_; boost::optional rd_; boost::variant 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; diff --git a/scripts/install-dependencies.sh b/scripts/install-dependencies.sh index 7e3421cd..d6b31dd3 100755 --- a/scripts/install-dependencies.sh +++ b/scripts/install-dependencies.sh @@ -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