From 6bdc9fe7ff98f6d76fc9f959b8c39e993a064216 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 12 Nov 2019 16:16:37 +0000 Subject: Performance fixes --- icespider/common/pathparts.cpp | 3 ++- icespider/core/xwwwFormUrlEncoded.h | 2 +- icespider/fcgi/cgiRequestBase.cpp | 32 +++++++++---------------- icespider/fcgi/cgiRequestBase.h | 5 +--- icespider/testing/testRequest.cpp | 3 ++- icespider/unittests/testFcgi.cpp | 48 +++++++++++++++++++++++++++++++++++++ 6 files changed, 65 insertions(+), 28 deletions(-) diff --git a/icespider/common/pathparts.cpp b/icespider/common/pathparts.cpp index 16c8d63..aabdd13 100644 --- a/icespider/common/pathparts.cpp +++ b/icespider/common/pathparts.cpp @@ -5,6 +5,7 @@ namespace ba = boost::algorithm; namespace IceSpider { + const auto slash = ba::first_finder("/", ba::is_equal()); Path::Path(const std::string_view & p) : path(p) { @@ -12,7 +13,7 @@ namespace IceSpider { if (relp.empty()) { return; } - for (auto pi = ba::make_split_iterator(relp, ba::first_finder("/", ba::is_equal())); pi != decltype(pi)(); ++pi) { + for (auto pi = ba::make_split_iterator(relp, slash); pi != decltype(pi)(); ++pi) { std::string_view pp(pi->begin(), pi->end() - pi->begin()); if (pp.front() == '{' && pp.back() == '}') { parts.push_back(std::make_unique(pp)); diff --git a/icespider/core/xwwwFormUrlEncoded.h b/icespider/core/xwwwFormUrlEncoded.h index 20f4ce6..d09b0c4 100644 --- a/icespider/core/xwwwFormUrlEncoded.h +++ b/icespider/core/xwwwFormUrlEncoded.h @@ -8,7 +8,7 @@ namespace IceSpider { class XWwwFormUrlEncoded : public Slicer::Deserializer { public: - typedef std::function KVh; + typedef std::function KVh; XWwwFormUrlEncoded(std::istream & in); diff --git a/icespider/fcgi/cgiRequestBase.cpp b/icespider/fcgi/cgiRequestBase.cpp index ab4d5e8..b6d5a77 100644 --- a/icespider/fcgi/cgiRequestBase.cpp +++ b/icespider/fcgi/cgiRequestBase.cpp @@ -15,9 +15,10 @@ using namespace std::literals; #define CGI_CONST(NAME) static const std::string_view NAME(#NAME) namespace IceSpider { - static const std::string_view amp("&"); - static const std::string_view semi("; "); - static const std::string_view HEADER_PREFIX("HTTP_"); + static const auto slash_pred = boost::algorithm::is_any_of("/"); + constexpr std::string_view amp("&"); + constexpr std::string_view semi("; "); + constexpr std::string_view HEADER_PREFIX("HTTP_"); CGI_CONST(REDIRECT_URL); CGI_CONST(SCRIPT_NAME); CGI_CONST(QUERY_STRING); @@ -46,43 +47,32 @@ namespace IceSpider { mapVars(const std::string_view & vn, const in & envmap, out & map, const std::string_view & sp) { auto qs = envmap.find(vn); if (qs != envmap.end()) { - XWwwFormUrlEncoded::iterateVars(qs->second, [&map](const auto && k, const auto && v) { + XWwwFormUrlEncoded::iterateVars(qs->second, [&map](auto && k, auto && v) { map.emplace(std::move(k), std::move(v)); }, sp); } } - template - const std::string_view & - findFirstOrElse(const Map &) - { - throw Ex(); - } - template const std::string_view & findFirstOrElse(const Map & map, const std::string_view & k, const Ks & ... ks) { - auto i = map.find(k); - if (i == map.end()) { + if (const auto i = map.find(k); i != map.end()) { + return i->second; + } + if constexpr (sizeof...(ks)) { return findFirstOrElse(map, ks...); } - return i->second; - } - - bool CgiRequestBase::ciLess::operator() (const std::string_view & s1, const std::string_view & s2) const - { - return lexicographical_compare(s1, s2, ba::is_iless()); + throw Ex(); } void CgiRequestBase::initialize() { - namespace ba = boost::algorithm; if (auto path = findFirstOrElse(envmap, REDIRECT_URL, SCRIPT_NAME).substr(1); // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) !path.empty()) { - ba::split(pathElements, path, ba::is_any_of("/"), ba::token_compress_off); + ba::split(pathElements, path, slash_pred, ba::token_compress_off); } mapVars(QUERY_STRING, envmap, qsmap, amp); diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h index fca2e41..88bc473 100644 --- a/icespider/fcgi/cgiRequestBase.h +++ b/icespider/fcgi/cgiRequestBase.h @@ -14,11 +14,8 @@ namespace IceSpider { void initialize(); public: - struct ciLess { - bool operator()(const std::string_view & s1, const std::string_view & s2) const; - }; typedef std::map VarMap; - typedef std::map HdrMap; + typedef std::map HdrMap; const PathElements & getRequestPath() const override; PathElements & getRequestPath() override; diff --git a/icespider/testing/testRequest.cpp b/icespider/testing/testRequest.cpp index b866308..080c07e 100644 --- a/icespider/testing/testRequest.cpp +++ b/icespider/testing/testRequest.cpp @@ -4,6 +4,7 @@ #include namespace IceSpider { + constexpr std::string_view slash("/"); TestRequest::TestRequest(const Core * c, HttpMethod m, const std::string_view & p) : IHttpRequest(c), method(m) @@ -13,7 +14,7 @@ namespace IceSpider { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) if (!path.empty()) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - ba::split(url, path, ba::is_any_of("/"), ba::token_compress_off); + ba::split(url, path, ba::is_any_of(slash), ba::token_compress_off); } } diff --git a/icespider/unittests/testFcgi.cpp b/icespider/unittests/testFcgi.cpp index d543678..c77edeb 100644 --- a/icespider/unittests/testFcgi.cpp +++ b/icespider/unittests/testFcgi.cpp @@ -258,6 +258,54 @@ BOOST_AUTO_TEST_CASE( postxwwwformurlencoded_simple ) BOOST_REQUIRE_EQUAL(314, n); } +BOOST_AUTO_TEST_CASE( reqParsePerf ) +{ + CharPtrPtrArray env ({ + "CONTEXT_DOCUMENT_ROOT=/var/www/shared/vhosts/sys.randomdan.homeip.net", + "CONTEXT_PREFIX=", + "DOCUMENT_ROOT=/var/www/shared/vhosts/sys.randomdan.homeip.net", + "GATEWAY_INTERFACE=CGI/1.1", + "H2PUSH=on", + "H2_PUSH=on", + "H2_PUSHED=", + "H2_PUSHED_ON=", + "H2_STREAM_ID=1", + "H2_STREAM_TAG=137-1", + "HTTP2=on", + "HTTPS=on", + "HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", + "HTTP_ACCEPT_ENCODING=gzip, deflate, br", + "HTTP_ACCEPT_LANGUAGE=en,en-GB;q=0.9", + "HTTP_HOST=sys.randomdan.homeip.net", + "HTTP_SEC_FETCH_SITE=none", + "HTTP_UPGRADE_INSECURE_REQUESTS=1", + "HTTP_USER_AGENT=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "PWD=/var/www/shared/files/localhost", + "QUERY_STRING=", + "REMOTE_ADDR=10.10.0.189", + "REMOTE_PORT=44030", + "REQUEST_METHOD=GET", + "REQUEST_SCHEME=https", + "REQUEST_URI=/env.cgi", + "SCRIPT_FILENAME=/var/www/shared/vhosts/sys.randomdan.homeip.net/env.cgi", + "SCRIPT_NAME=/env.cgi", + "SERVER_ADDR=fdc7:602:e9c5:b8f0::3", + "SERVER_ADMIN=dan.goodliffe@randomdan.homeip.net", + "SERVER_NAME=sys.randomdan.homeip.net", + "SERVER_PORT=443", + "SERVER_PROTOCOL=HTTP/2.0", + "SERVER_SIGNATURE=
Apache/2.4.41 (Gentoo) mod_fcgid/2.3.9 PHP/7.2.23 OpenSSL/1.1.1d mod_perl/2.0.10 Perl/v5.30.0 Server at sys.randomdan.homeip.net Port 443
", + "SERVER_SOFTWARE=Apache/2.4.41 (Gentoo) mod_fcgid/2.3.9 PHP/7.2.23 OpenSSL/1.1.1d mod_perl/2.0.10 Perl/v5.30.0", + "SHLVL=0", + "SSL_TLS_SNI=sys.randomdan.homeip.net", + }); + for (int x = 0; x < 10000; x +=1) { + TestRequest req(this, env); + } +} + + BOOST_AUTO_TEST_CASE( postxwwwformurlencoded_dictionary ) { CharPtrPtrArray env ({ "SCRIPT_NAME=/", "REQUEST_METHOD=No", "CONTENT_TYPE=application/x-www-form-urlencoded" }); -- cgit v1.2.3