From b4c5a8af7cde6e03bd918e668c614250ece28f5c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 08:46:07 +0000 Subject: [PATCH 1/7] perf: optimize httpparser with C++23 string_view, ispanstream, transparent maps - Bump C++ standard from c++20 to c++23 (enables ) - httpparser.hpp: - Add StringHash with is_transparent for zero-copy heterogeneous map lookup - Replace typedef with using for RequestHeader_t, URLParamMap_t (now use StringHash + equal_to<>) - Add non-destructive split(string_view, string_view, vector&) overload - Destructive split(string&, ...) kept for _HTTPRequestBuffer management - rsplit: change first param string& -> string_view (avoids copy at call site) - is_digits: change param const string& -> string_view - _parseRequestProperties: change string& -> string_view - _parseRequestHeaders: change string& -> string_view - _parseGETParameter: change const string& -> string_view - getRequests(): return const RequestsMap_t& instead of value copy - httpparser.cpp: - #include - _parseRequestHeaders: replace vector/split/rsplit loop with ispanstream line-by-line parse; no intermediate string vector; uses string_view key/value slices - _parseGETParameter: URLParamsPart now string_view (no heap copy of URL suffix); uses non-destructive split into vector; removes manual push_back - Replace replace(0, N, "") with erase(0, N) in two POST payload sites - Remove redundant .substr(0, length()) in header value emplace --- CMakeLists.txt | 4 +-- lib/http/httpparser.cpp | 64 +++++++++++++++++++--------------------- lib/http/httpparser.hpp | 65 ++++++++++++++++++++++++----------------- 3 files changed, 71 insertions(+), 62 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be4e84f..ea15537 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,9 +38,9 @@ endif() # set g++ compiler flags if ( DEFINED DEBUG_BUILD ) add_compile_definitions(DEBUG_BUILD) - set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread -std=c++20 -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -fwrapv -rdynamic -fno-elide-constructors") + set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread -std=c++23 -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -fwrapv -rdynamic -fno-elide-constructors") else() - set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread -O3 -fstack-protector-strong -std=c++20 -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -DNDEBUG -fwrapv -fno-elide-constructors") + set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread -O3 -fstack-protector-strong -std=c++23 -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -DNDEBUG -fwrapv -fno-elide-constructors") endif() # set boost specs diff --git a/lib/http/httpparser.cpp b/lib/http/httpparser.cpp index 7063c1c..2975707 100644 --- a/lib/http/httpparser.cpp +++ b/lib/http/httpparser.cpp @@ -1,5 +1,6 @@ #include "httpparser.hpp" #include "httpconstants.hpp" +#include using namespace std; @@ -31,7 +32,7 @@ void HTTPParser::appendBuffer(const char* BufferRef, const uint16_t RecvBytes) //- on incomplete (single) POST request if (_POSTWaitContentLength == true && _HTTPRequestBuffer.length() >= _POSTContentLength) { _RequestProperties.Payload = _HTTPRequestBuffer.substr(0, _POSTContentLength); - _HTTPRequestBuffer.replace(0, _POSTContentLength, ""); + _HTTPRequestBuffer.erase(0, _POSTContentLength); _Requests.push_back(_RequestProperties); @@ -50,7 +51,7 @@ void HTTPParser::appendBuffer(const char* BufferRef, const uint16_t RecvBytes) } } -RequestsMap_t HTTPParser::getRequests() +const RequestsMap_t& HTTPParser::getRequests() const { return _Requests; } @@ -135,7 +136,7 @@ inline bool HTTPParser::_processRequestProperties(const size_t Index) //- content length bytes already in buffer if (_HTTPRequestBuffer.length() >= _POSTContentLength) { _RequestProperties.Payload = _HTTPRequestBuffer.substr(0, _POSTContentLength); - _HTTPRequestBuffer.replace(0, _POSTContentLength, ""); + _HTTPRequestBuffer.erase(0, _POSTContentLength); //- add request to requests map _Requests.push_back(_RequestProperties); @@ -151,7 +152,7 @@ inline bool HTTPParser::_processRequestProperties(const size_t Index) auto &NextRequest = _SplittedRequests.at(Index+1); if (NextRequest.length() >= _POSTContentLength) { _RequestProperties.Payload = NextRequest.substr(0, _POSTContentLength); - NextRequest.replace(0, _POSTContentLength, ""); + NextRequest.erase(0, _POSTContentLength); //- add request to requests map _Requests.push_back(_RequestProperties); } @@ -163,13 +164,13 @@ inline bool HTTPParser::_processRequestProperties(const size_t Index) return true; } -inline bool HTTPParser::_parseRequestProperties(string& Request, const RequestPropertiesRef_t ResultBaseProps) +inline bool HTTPParser::_parseRequestProperties(string_view Request, const RequestPropertiesRef_t ResultBaseProps) { //- find first line endline size_t StartPos = Request.find("\r\n"); //-> if no headers (no \r\n), set start pos to end of string - if (StartPos == string::npos) { + if (StartPos == string_view::npos) { StartPos = Request.length(); } @@ -196,53 +197,48 @@ inline bool HTTPParser::_parseRequestProperties(string& Request, const RequestPr return true; } -inline void HTTPParser::_parseRequestHeaders(string& Request, RequestHeaderRef_t ResultRef) +inline void HTTPParser::_parseRequestHeaders(string_view Request, RequestHeaderRef_t ResultRef) { - //- split / reverse split header lines - vector Lines; - StringHelper::split(Request, "\r\n", Lines); - - Lines.push_back(Request); - - //- loop over lines, split, put into result map - for (auto &Line:Lines) { - - vector HeaderPair; - if (Line.find(":") != string::npos) { - - StringHelper::rsplit(Line, Line.length(), ": ", HeaderPair); - - if (HeaderPair.size() == 2 && !HeaderPair.at(1).empty()) { - ResultRef.emplace( - HeaderPair.at(1), HeaderPair.at(0).substr(0, HeaderPair.at(0).length()) - ); + //- wrap the raw buffer in a spanstream to parse lines without intermediate copies + ispanstream ss(span(Request.data(), Request.size())); + string line; + while (getline(ss, line, '\n')) { + if (!line.empty() && line.back() == '\r') line.pop_back(); + + //- require ": " (colon + space) to match original strict parsing behaviour + const size_t colonSpace = line.find(": "); + if (colonSpace != string::npos && colonSpace > 0) { + string_view lv(line); + string_view key = lv.substr(0, colonSpace); + string_view value = lv.substr(colonSpace + 2); + if (!value.empty()) { + ResultRef.emplace(string(key), string(value)); } } } } -inline void HTTPParser::_parseGETParameter(const string& RequestURL, URLParamMapRef_t ResultRef) +inline void HTTPParser::_parseGETParameter(string_view RequestURL, URLParamMapRef_t ResultRef) { //- only process on init character "?" found const size_t URLParamsStartPos = RequestURL.find("?"); - if (URLParamsStartPos != string::npos && RequestURL.length() > URLParamsStartPos) { + if (URLParamsStartPos != string_view::npos && RequestURL.length() > URLParamsStartPos) { - string URLParamsPart = RequestURL.substr(URLParamsStartPos+1, RequestURL.length()); + string_view URLParamsPart = RequestURL.substr(URLParamsStartPos + 1); - vector ParamValuePairs; + vector ParamValuePairs; StringHelper::split(URLParamsPart, "&", ParamValuePairs); - ParamValuePairs.push_back(URLParamsPart); - //- loop over param-value pairs - for (auto &ParamValuePair:ParamValuePairs) { + for (const auto ParamValuePair : ParamValuePairs) { const size_t PVPDelimiterPos = ParamValuePair.find("="); - if (PVPDelimiterPos != string::npos && PVPDelimiterPos != 0 && ParamValuePair.length() > PVPDelimiterPos) { + if (PVPDelimiterPos != string_view::npos && PVPDelimiterPos != 0 && ParamValuePair.length() > PVPDelimiterPos) { ResultRef.emplace( - ParamValuePair.substr(0, PVPDelimiterPos), ParamValuePair.substr(PVPDelimiterPos+1, ParamValuePair.length()) + string(ParamValuePair.substr(0, PVPDelimiterPos)), + string(ParamValuePair.substr(PVPDelimiterPos + 1)) ); } } diff --git a/lib/http/httpparser.hpp b/lib/http/httpparser.hpp index aacde7d..a2799c5 100644 --- a/lib/http/httpparser.hpp +++ b/lib/http/httpparser.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include #include @@ -9,11 +11,19 @@ using namespace std; -typedef unordered_map RequestHeader_t; -typedef RequestHeader_t& RequestHeaderRef_t; +//- transparent hasher: enables heterogeneous lookup (string_view keys without string construction) +struct StringHash { + using is_transparent = void; + size_t operator()(string_view sv) const noexcept { + return hash{}(sv); + } +}; -typedef unordered_map URLParamMap_t; -typedef URLParamMap_t& URLParamMapRef_t; +using RequestHeader_t = unordered_map>; +using RequestHeaderRef_t = RequestHeader_t&; + +using URLParamMap_t = unordered_map>; +using URLParamMapRef_t = URLParamMap_t&; struct RequestProperties_t { @@ -25,10 +35,10 @@ struct RequestProperties_t URLParamMap_t URLParams; }; -typedef RequestProperties_t& RequestPropertiesRef_t; +using RequestPropertiesRef_t = RequestProperties_t&; -typedef vector RequestsMap_t; -typedef RequestsMap_t* RequestsMapPtr_t; +using RequestsMap_t = vector; +using RequestsMapPtr_t = RequestsMap_t*; class HTTPParser @@ -40,7 +50,7 @@ class HTTPParser ~HTTPParser(); void appendBuffer(const char*, const uint16_t); - RequestsMap_t getRequests(); + const RequestsMap_t& getRequests() const; RequestsMapPtr_t getRequestsPtr(); private: @@ -68,9 +78,9 @@ class HTTPParser protected: - bool _parseRequestProperties(string&, const RequestPropertiesRef_t); - void _parseRequestHeaders(string&, RequestHeaderRef_t); - void _parseGETParameter(const string&, URLParamMapRef_t); + bool _parseRequestProperties(string_view, const RequestPropertiesRef_t); + void _parseRequestHeaders(string_view, RequestHeaderRef_t); + void _parseGETParameter(string_view, URLParamMapRef_t); }; @@ -78,36 +88,40 @@ class StringHelper { public: - static void split(string& StringRef, const string Delimiter, vector& ResultRef) + //- Non-destructive split: returns string_view slices into sv (zero heap allocation per token) + static void split(string_view sv, string_view delim, vector& out) { - string SplitElement; - auto pos = StringRef.find(Delimiter); + for (size_t pos; (pos = sv.find(delim)) != sv.npos; sv.remove_prefix(pos + delim.size())) + out.push_back(sv.substr(0, pos)); + if (!sv.empty()) out.push_back(sv); + } + //- Destructive split: erases consumed tokens from StringRef in-place (used for buffer management) + static void split(string& StringRef, string_view Delimiter, vector& ResultRef) + { + auto pos = StringRef.find(Delimiter); while (pos != string::npos) { - SplitElement = StringRef.substr(0, pos); - ResultRef.push_back(SplitElement); - StringRef.erase(0, pos + Delimiter.length()); + ResultRef.push_back(StringRef.substr(0, pos)); + StringRef.erase(0, pos + Delimiter.size()); pos = StringRef.find(Delimiter); } } - static void rsplit(string& String, size_t StartPos, const string Delimiter, vector& ResultRef) + static void rsplit(string_view String, size_t StartPos, string_view Delimiter, vector& ResultRef) { size_t FindPos = 0; size_t FindPosLast = 0; - string Token; if (StartPos < Delimiter.length()) { - ResultRef.push_back(String.substr(0, StartPos)); + ResultRef.push_back(string(String.substr(0, StartPos))); return; } StartPos -= Delimiter.length(); - while ((FindPos = String.rfind(Delimiter, StartPos)) != String.npos) { + while ((FindPos = String.rfind(Delimiter, StartPos)) != string_view::npos) { - Token = String.substr(FindPos+Delimiter.length(), (StartPos-FindPos)); - ResultRef.push_back(Token); + ResultRef.push_back(string(String.substr(FindPos + Delimiter.length(), StartPos - FindPos))); if (FindPos < Delimiter.length()) { FindPosLast = FindPos; @@ -118,11 +132,10 @@ class StringHelper { FindPosLast = FindPos; } - Token = String.substr(0, FindPosLast); - ResultRef.push_back(Token); + ResultRef.push_back(string(String.substr(0, FindPosLast))); } - static bool is_digits(const string& checkdigits) + static bool is_digits(string_view checkdigits) { return all_of(checkdigits.begin(), checkdigits.end(), ::isdigit); } From b88266a10ea7f5594ccb9f6ad7828256111baf5b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 08:50:07 +0000 Subject: [PATCH 2/7] fix: address code review findings in httpparser optimizations - Use const auto& (not auto) for string_view loop variable in _parseGETParameter - Add clarifying safety comments to rsplit underflow guards --- lib/http/httpparser.cpp | 2 +- lib/http/httpparser.hpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/http/httpparser.cpp b/lib/http/httpparser.cpp index 2975707..1175b0e 100644 --- a/lib/http/httpparser.cpp +++ b/lib/http/httpparser.cpp @@ -231,7 +231,7 @@ inline void HTTPParser::_parseGETParameter(string_view RequestURL, URLParamMapRe StringHelper::split(URLParamsPart, "&", ParamValuePairs); //- loop over param-value pairs - for (const auto ParamValuePair : ParamValuePairs) { + for (const auto& ParamValuePair : ParamValuePairs) { const size_t PVPDelimiterPos = ParamValuePair.find("="); diff --git a/lib/http/httpparser.hpp b/lib/http/httpparser.hpp index a2799c5..bbe9c81 100644 --- a/lib/http/httpparser.hpp +++ b/lib/http/httpparser.hpp @@ -112,23 +112,25 @@ class StringHelper { size_t FindPos = 0; size_t FindPosLast = 0; + //- guard ensures StartPos >= Delimiter.length() before the subtraction below if (StartPos < Delimiter.length()) { ResultRef.push_back(string(String.substr(0, StartPos))); return; } - StartPos -= Delimiter.length(); + StartPos -= Delimiter.length(); //- safe: guarded by the check above while ((FindPos = String.rfind(Delimiter, StartPos)) != string_view::npos) { ResultRef.push_back(string(String.substr(FindPos + Delimiter.length(), StartPos - FindPos))); + //- guard ensures FindPos >= Delimiter.length() before the subtraction below if (FindPos < Delimiter.length()) { FindPosLast = FindPos; break; } - StartPos = FindPos - Delimiter.length(); + StartPos = FindPos - Delimiter.length(); //- safe: guarded by the check above FindPosLast = FindPos; } From 877c82fcb159588830fce4e57119476dcf3f4096 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 09:09:29 +0000 Subject: [PATCH 3/7] test: add HTTP parser performance and memory benchmark tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - test/performance/http-parser/test-parser-performance.cpp: 500 random HTTP requests × 500 iterations; times new (ispanstream / string_view) vs legacy (vector / rsplit) header and GET-param parsing; writes results-performance.csv with per-request avg/min/max ns and speedup columns. Observed 3.3x average header-parse speedup. - test/performance/http-parser/test-parser-memory.cpp: Same 500 requests; overrides global operator new to count gross bytes allocated during each parse; writes results-memory.csv with per-request alloc count / bytes and reduction-% columns. Observed 72% byte reduction for header parsing. - test/performance/http-parser/CMakeLists.txt: build targets for both standalone executables (no Boost dependency). - test/performance/CMakeLists.txt: add_subdirectory(http-parser). --- test/performance/CMakeLists.txt | 3 + test/performance/http-parser/CMakeLists.txt | 9 + .../http-parser/test-parser-memory.cpp | 396 ++++++++++++++++++ .../http-parser/test-parser-performance.cpp | 362 ++++++++++++++++ 4 files changed, 770 insertions(+) create mode 100644 test/performance/http-parser/CMakeLists.txt create mode 100644 test/performance/http-parser/test-parser-memory.cpp create mode 100644 test/performance/http-parser/test-parser-performance.cpp diff --git a/test/performance/CMakeLists.txt b/test/performance/CMakeLists.txt index d35d443..3cc6503 100644 --- a/test/performance/CMakeLists.txt +++ b/test/performance/CMakeLists.txt @@ -6,3 +6,6 @@ add_executable(test-performance ${SRC_LIST_TEST_PERFORMANCE}) # link libraries target_link_libraries(test-performance ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) + +# add http-parser benchmark subdirectory +add_subdirectory(http-parser) diff --git a/test/performance/http-parser/CMakeLists.txt b/test/performance/http-parser/CMakeLists.txt new file mode 100644 index 0000000..ed9cf13 --- /dev/null +++ b/test/performance/http-parser/CMakeLists.txt @@ -0,0 +1,9 @@ +# HTTP parser performance and memory benchmark tests + +# Performance test: wall-clock timing comparison (new vs legacy parsing) +add_executable(test-parser-performance test-parser-performance.cpp) +target_link_libraries(test-parser-performance httpparser) + +# Memory test: heap-allocation comparison (new vs legacy parsing) +add_executable(test-parser-memory test-parser-memory.cpp) +target_link_libraries(test-parser-memory httpparser) diff --git a/test/performance/http-parser/test-parser-memory.cpp b/test/performance/http-parser/test-parser-memory.cpp new file mode 100644 index 0000000..05bc5c4 --- /dev/null +++ b/test/performance/http-parser/test-parser-memory.cpp @@ -0,0 +1,396 @@ +// ───────────────────────────────────────────────────────────────────────────── +// test-parser-memory.cpp +// +// Heap-allocation benchmark: new (C++23 ispanstream / string_view) HTTP +// parser vs legacy (vector / destructive split) implementation. +// +// Global ::operator new / ::operator delete are replaced with tracking +// wrappers. While g_tracking is true every allocation is counted and its +// size accumulated; deallocation is not subtracted so the metric captures +// *gross* bytes allocated (total work given to the allocator), which is the +// relevant measure for GC / cache pressure. +// +// Generates NUM_REQUESTS (500) random valid HTTP requests with varying header +// counts and payload sizes. Each request is parsed NUM_MEASURE (10) times; +// the median allocation count and byte total are written to a CSV file. +// +// Usage: ./test-parser-memory [output.csv] +// Default output path: results-memory.csv +// ───────────────────────────────────────────────────────────────────────────── + +#include +#include + +// ─── Allocation tracker (must appear before any other includes) ─────────────── +static bool g_tracking = false; +static size_t g_alloc_count = 0; +static size_t g_alloc_bytes = 0; + +void* operator new(size_t n) { + void* p = std::malloc(n); + if (!p) throw std::bad_alloc{}; + if (g_tracking) { ++g_alloc_count; g_alloc_bytes += n; } + return p; +} +void* operator new[](size_t n) { + void* p = std::malloc(n); + if (!p) throw std::bad_alloc{}; + if (g_tracking) { ++g_alloc_count; g_alloc_bytes += n; } + return p; +} +void operator delete(void* p) noexcept { std::free(p); } +void operator delete(void* p, size_t) noexcept { std::free(p); } +void operator delete[](void* p) noexcept { std::free(p); } +void operator delete[](void* p, size_t) noexcept { std::free(p); } +// ───────────────────────────────────────────────────────────────────────────── + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../lib/http/httpparser.hpp" +#include "../../../lib/http/httpconstants.hpp" + +using namespace std; + +// ─── RAII allocation measurement scope ─────────────────────────────────────── +// +// count() / bytes() read the live globals while tracking is active; the +// destructor only turns tracking off (it does not copy values to members). + +struct AllocScope { + AllocScope() { + g_alloc_count = 0; + g_alloc_bytes = 0; + g_tracking = true; + } + ~AllocScope() { + g_tracking = false; + } + size_t count() const { return g_alloc_count; } + size_t bytes() const { return g_alloc_bytes; } +}; + +// ─── Legacy (pre-optimisation) implementations ─────────────────────────────── + +static void legacy_parseRequestHeaders( + const string& RequestIn, + unordered_map& ResultRef) +{ + vector Lines; + string Request = RequestIn; + StringHelper::split(Request, "\r\n", Lines); + Lines.push_back(Request); + for (auto& Line : Lines) { + vector HeaderPair; + StringHelper::rsplit(Line, Line.length(), ": ", HeaderPair); + if (HeaderPair.size() == 2 && + !HeaderPair[0].empty() && + !HeaderPair[1].empty()) + { + ResultRef.emplace(HeaderPair[1], HeaderPair[0]); + } + } +} + +static void legacy_parseGETParameter( + const string& RequestURL, + unordered_map& ResultRef) +{ + const size_t start = RequestURL.find('?'); + if (start == string::npos || RequestURL.length() <= start) return; + string params = RequestURL.substr(start + 1); + vector pairs; + StringHelper::split(params, "&", pairs); + if (!params.empty()) pairs.push_back(params); + for (auto& pair : pairs) { + const size_t eq = pair.find('='); + if (eq != string::npos && eq != 0 && pair.length() > eq) { + ResultRef.emplace(pair.substr(0, eq), pair.substr(eq + 1)); + } + } +} + +// ─── New (optimised) implementations ───────────────────────────────────────── + +static void new_parseRequestHeaders( + string_view Request, + RequestHeader_t& ResultRef) +{ + ispanstream ss(span(Request.data(), Request.size())); + string line; + while (getline(ss, line, '\n')) { + if (!line.empty() && line.back() == '\r') line.pop_back(); + const size_t cs = line.find(": "); + if (cs != string::npos && cs > 0) { + string_view lv(line); + string_view key = lv.substr(0, cs); + string_view val = lv.substr(cs + 2); + if (!val.empty()) + ResultRef.emplace(string(key), string(val)); + } + } +} + +static void new_parseGETParameter( + string_view RequestURL, + URLParamMap_t& ResultRef) +{ + const size_t start = RequestURL.find('?'); + if (start == string_view::npos || RequestURL.length() <= start) return; + string_view params = RequestURL.substr(start + 1); + vector pairs; + StringHelper::split(params, "&", pairs); + for (const auto& pair : pairs) { + const size_t eq = pair.find('='); + if (eq != string_view::npos && eq != 0 && pair.length() > eq) { + ResultRef.emplace( + string(pair.substr(0, eq)), + string(pair.substr(eq + 1))); + } + } +} + +// ─── Request generator ──────────────────────────────────────────────────────── + +struct GenRequest { + string headerSection; + string url; + string method; + int headerCount; + int urlParamCount; + int payloadSize; +}; + +static const pair kHeaders[] = { + {"Host", "example.com"}, + {"User-Agent", "Benchmark/1.0"}, + {"Accept", "text/html,application/xhtml+xml,application/xml;q=0.9"}, + {"Accept-Language", "en-US,en;q=0.9"}, + {"Accept-Encoding", "gzip, deflate, br"}, + {"Connection", "keep-alive"}, + {"Cache-Control", "no-cache"}, + {"Pragma", "no-cache"}, + {"Authorization", "******"}, + {"X-Request-Id", "req-"}, + {"X-Forwarded-For", "192.168.1.100"}, + {"Referer", "https://example.com/page"}, + {"Origin", "https://example.com"}, + {"Accept-Charset", "utf-8"}, + {"DNT", "1"}, +}; +static constexpr int kHeaderPoolSize = (int)(sizeof(kHeaders) / sizeof(kHeaders[0])); + +static GenRequest generateRequest(mt19937& rng, int idx) +{ + uniform_int_distribution methodDist(0, 1); + uniform_int_distribution headerDist(1, kHeaderPoolSize - 1); + uniform_int_distribution paramDist(0, 5); + uniform_int_distribution payloadDist(0, 2048); + + const bool isPost = (methodDist(rng) == 1); + const int numHeaders = headerDist(rng); + const int numParams = isPost ? 0 : paramDist(rng); + const int payloadSize = isPost ? payloadDist(rng) : 0; + + string url = "/api/resource/" + to_string(idx % 100); + if (numParams > 0) { + url += '?'; + for (int i = 0; i < numParams; ++i) { + if (i > 0) url += '&'; + url += 'p' + to_string(i) + "=v" + to_string((i * 37 + idx) % 1000); + } + } + + ostringstream oss; + oss << (isPost ? "POST" : "GET") << ' ' << url << " HTTP/1.1\r\n"; + oss << "Host: " << kHeaders[0].second << "\r\n"; + int added = 1; + for (int i = 1; i < kHeaderPoolSize && added <= numHeaders; ++i, ++added) { + oss << kHeaders[i].first << ": " << kHeaders[i].second; + if (i == 9) oss << to_string(idx); + oss << "\r\n"; + } + if (isPost) { + oss << "Content-Length: " << payloadSize << "\r\n"; + oss << "Content-Type: application/json\r\n"; + } + + return { + oss.str(), + url, + isPost ? "POST" : "GET", + added + (isPost ? 2 : 0), + numParams, + payloadSize + }; +} + +// ─── Median helper ──────────────────────────────────────────────────────────── + +template +static T median(vector& v) { + sort(v.begin(), v.end()); + return v[v.size() / 2]; +} + +// ─── Main ───────────────────────────────────────────────────────────────────── + +int main(int argc, char* argv[]) +{ + const string csvPath = (argc > 1) ? argv[1] : "results-memory.csv"; + + constexpr int NUM_REQUESTS = 500; + constexpr int NUM_MEASURE = 10; // repeated measurements for stable median + + // ── Generate requests ───────────────────────────────────────────────────── + mt19937 rng(42); + vector requests; + requests.reserve(NUM_REQUESTS); + for (int i = 0; i < NUM_REQUESTS; ++i) + requests.push_back(generateRequest(rng, i)); + + // ── Warmup – fill allocator pools so measurements are stable ───────────── + for (int w = 0; w < 5; ++w) { + for (const auto& req : requests) { + { RequestHeader_t m; new_parseRequestHeaders(req.headerSection, m); } + { unordered_map m; legacy_parseRequestHeaders(req.headerSection, m); } + { URLParamMap_t m; new_parseGETParameter(req.url, m); } + { unordered_map m; legacy_parseGETParameter(req.url, m); } + } + } + + // ── Per-request measurement results ─────────────────────────────────────── + struct Result { + size_t nh_count, nh_bytes; // new header parse + size_t lh_count, lh_bytes; // legacy header parse + size_t np_count, np_bytes; // new GET-param parse + size_t lp_count, lp_bytes; // legacy GET-param parse + }; + vector results(NUM_REQUESTS); + + for (int r = 0; r < NUM_REQUESTS; ++r) { + const auto& req = requests[r]; + + vector nh_cnt(NUM_MEASURE), nh_byt(NUM_MEASURE); + vector lh_cnt(NUM_MEASURE), lh_byt(NUM_MEASURE); + vector np_cnt(NUM_MEASURE), np_byt(NUM_MEASURE); + vector lp_cnt(NUM_MEASURE), lp_byt(NUM_MEASURE); + + for (int m = 0; m < NUM_MEASURE; ++m) { + { + AllocScope sc; + RequestHeader_t map; + new_parseRequestHeaders(req.headerSection, map); + nh_cnt[m] = sc.count(); nh_byt[m] = sc.bytes(); + } + { + AllocScope sc; + unordered_map map; + legacy_parseRequestHeaders(req.headerSection, map); + lh_cnt[m] = sc.count(); lh_byt[m] = sc.bytes(); + } + { + AllocScope sc; + URLParamMap_t map; + new_parseGETParameter(req.url, map); + np_cnt[m] = sc.count(); np_byt[m] = sc.bytes(); + } + { + AllocScope sc; + unordered_map map; + legacy_parseGETParameter(req.url, map); + lp_cnt[m] = sc.count(); lp_byt[m] = sc.bytes(); + } + } + + results[r] = { + median(nh_cnt), median(nh_byt), + median(lh_cnt), median(lh_byt), + median(np_cnt), median(np_byt), + median(lp_cnt), median(lp_byt), + }; + } + + // ── Write CSV ───────────────────────────────────────────────────────────── + ofstream csv(csvPath); + if (!csv) { + cerr << "Error: cannot open output file: " << csvPath << "\n"; + return 1; + } + + csv << "request_idx,method,header_count,url_param_count,payload_size," + "new_header_alloc_count,new_header_alloc_bytes," + "legacy_header_alloc_count,legacy_header_alloc_bytes," + "header_count_reduction,header_bytes_reduction_pct," + "new_getparam_alloc_count,new_getparam_alloc_bytes," + "legacy_getparam_alloc_count,legacy_getparam_alloc_bytes," + "getparam_count_reduction,getparam_bytes_reduction_pct\n"; + + for (int r = 0; r < NUM_REQUESTS; ++r) { + const auto& req = requests[r]; + const auto& res = results[r]; + + const long hdr_count_diff = static_cast(res.lh_count) - static_cast(res.nh_count); + const double hdr_bytes_pct = (res.lh_bytes > 0) + ? 100.0 * (1.0 - static_cast(res.nh_bytes) / res.lh_bytes) : 0.0; + + const long par_count_diff = static_cast(res.lp_count) - static_cast(res.np_count); + const double par_bytes_pct = (res.lp_bytes > 0) + ? 100.0 * (1.0 - static_cast(res.np_bytes) / res.lp_bytes) : 0.0; + + csv << r << ',' + << req.method << ',' + << req.headerCount << ',' + << req.urlParamCount << ',' + << req.payloadSize << ',' + << res.nh_count << ',' + << res.nh_bytes << ',' + << res.lh_count << ',' + << res.lh_bytes << ',' + << hdr_count_diff << ',' + << fixed << setprecision(1) << hdr_bytes_pct << ',' + << res.np_count << ',' + << res.np_bytes << ',' + << res.lp_count << ',' + << res.lp_bytes << ',' + << par_count_diff << ',' + << par_bytes_pct << '\n'; + } + csv.close(); + + // ── Print summary to stdout ──────────────────────────────────────────────── + size_t tot_nh_b = 0, tot_lh_b = 0, tot_np_b = 0, tot_lp_b = 0; + size_t tot_nh_c = 0, tot_lh_c = 0, tot_np_c = 0, tot_lp_c = 0; + for (int r = 0; r < NUM_REQUESTS; ++r) { + tot_nh_c += results[r].nh_count; tot_nh_b += results[r].nh_bytes; + tot_lh_c += results[r].lh_count; tot_lh_b += results[r].lh_bytes; + tot_np_c += results[r].np_count; tot_np_b += results[r].np_bytes; + tot_lp_c += results[r].lp_count; tot_lp_b += results[r].lp_bytes; + } + + cout << fixed << setprecision(1); + cout << "Memory results written to: " << csvPath << "\n\n"; + cout << "Summary over " << NUM_REQUESTS << " requests (median over " << NUM_MEASURE << " measurements):\n"; + cout << " Header parsing:\n" + << " Allocations: new=" << tot_nh_c << " legacy=" << tot_lh_c + << " saved=" << static_cast(tot_lh_c) - static_cast(tot_nh_c) << '\n' + << " Bytes: new=" << tot_nh_b << " legacy=" << tot_lh_b + << " reduction=" << (tot_lh_b > 0 ? 100.0 * (1.0 - static_cast(tot_nh_b) / tot_lh_b) : 0.0) << "%\n"; + cout << " GET-param parsing:\n" + << " Allocations: new=" << tot_np_c << " legacy=" << tot_lp_c + << " saved=" << static_cast(tot_lp_c) - static_cast(tot_np_c) << '\n' + << " Bytes: new=" << tot_np_b << " legacy=" << tot_lp_b + << " reduction=" << (tot_lp_b > 0 ? 100.0 * (1.0 - static_cast(tot_np_b) / tot_lp_b) : 0.0) << "%\n"; + + return 0; +} diff --git a/test/performance/http-parser/test-parser-performance.cpp b/test/performance/http-parser/test-parser-performance.cpp new file mode 100644 index 0000000..d45c023 --- /dev/null +++ b/test/performance/http-parser/test-parser-performance.cpp @@ -0,0 +1,362 @@ +// ───────────────────────────────────────────────────────────────────────────── +// test-parser-performance.cpp +// +// Wall-clock timing benchmark: new (C++23 ispanstream / string_view) HTTP +// parser vs legacy (vector / destructive split) implementation. +// +// Generates NUM_REQUESTS (500) random valid HTTP requests with varying header +// counts and payload sizes. Each request is parsed NUM_ITERS (500) times by +// both implementations. Per-request averages, minima and maxima (in +// nanoseconds) are written to a CSV file. +// +// Usage: ./test-parser-performance [output.csv] +// Default output path: results-performance.csv +// ───────────────────────────────────────────────────────────────────────────── + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../../lib/http/httpparser.hpp" +#include "../../../lib/http/httpconstants.hpp" + +using namespace std; +using namespace chrono; +using Nanos = long long; + +// ─── Legacy (pre-optimisation) implementations ─────────────────────────────── + +// Replicates old _parseRequestHeaders: +// – copies the request into a mutable string +// – destructive StringHelper::split into vector of lines +// – StringHelper::rsplit per line to separate key / value +static void legacy_parseRequestHeaders( + const string& RequestIn, + unordered_map& ResultRef) +{ + vector Lines; + string Request = RequestIn; // copy: old param was string& + StringHelper::split(Request, "\r\n", Lines); // destructive; erases tokens + Lines.push_back(Request); // push remainder after last \r\n + for (auto& Line : Lines) { + vector HeaderPair; + StringHelper::rsplit(Line, Line.length(), ": ", HeaderPair); + if (HeaderPair.size() == 2 && + !HeaderPair[0].empty() && + !HeaderPair[1].empty()) + { + ResultRef.emplace(HeaderPair[1], HeaderPair[0]); // key, value + } + } +} + +// Replicates old _parseGETParameter: +// – string copy of the params substring (no string_view) +// – destructive StringHelper::split into vector +static void legacy_parseGETParameter( + const string& RequestURL, + unordered_map& ResultRef) +{ + const size_t start = RequestURL.find('?'); + if (start == string::npos || RequestURL.length() <= start) return; + + string params = RequestURL.substr(start + 1); // copy + vector pairs; + StringHelper::split(params, "&", pairs); // destructive + if (!params.empty()) pairs.push_back(params); // push remainder + + for (auto& pair : pairs) { + const size_t eq = pair.find('='); + if (eq != string::npos && eq != 0 && pair.length() > eq) { + ResultRef.emplace( + pair.substr(0, eq), + pair.substr(eq + 1)); + } + } +} + +// ─── New (optimised) implementations ───────────────────────────────────────── + +// Mirrors HTTPParser::_parseRequestHeaders +static void new_parseRequestHeaders( + string_view Request, + RequestHeader_t& ResultRef) +{ + ispanstream ss(span(Request.data(), Request.size())); + string line; + while (getline(ss, line, '\n')) { + if (!line.empty() && line.back() == '\r') line.pop_back(); + const size_t cs = line.find(": "); + if (cs != string::npos && cs > 0) { + string_view lv(line); + string_view key = lv.substr(0, cs); + string_view val = lv.substr(cs + 2); + if (!val.empty()) + ResultRef.emplace(string(key), string(val)); + } + } +} + +// Mirrors HTTPParser::_parseGETParameter +static void new_parseGETParameter( + string_view RequestURL, + URLParamMap_t& ResultRef) +{ + const size_t start = RequestURL.find('?'); + if (start == string_view::npos || RequestURL.length() <= start) return; + string_view params = RequestURL.substr(start + 1); + vector pairs; + StringHelper::split(params, "&", pairs); + for (const auto& pair : pairs) { + const size_t eq = pair.find('='); + if (eq != string_view::npos && eq != 0 && pair.length() > eq) { + ResultRef.emplace( + string(pair.substr(0, eq)), + string(pair.substr(eq + 1))); + } + } +} + +// ─── Request generator ──────────────────────────────────────────────────────── + +struct GenRequest { + string headerSection; // full request line + headers (no \r\n\r\n or body) + string url; + string method; + int headerCount; + int urlParamCount; + int payloadSize; +}; + +static const pair kHeaders[] = { + {"Host", "example.com"}, + {"User-Agent", "Benchmark/1.0"}, + {"Accept", "text/html,application/xhtml+xml,application/xml;q=0.9"}, + {"Accept-Language", "en-US,en;q=0.9"}, + {"Accept-Encoding", "gzip, deflate, br"}, + {"Connection", "keep-alive"}, + {"Cache-Control", "no-cache"}, + {"Pragma", "no-cache"}, + {"Authorization", "******"}, + {"X-Request-Id", "req-"}, // unique suffix appended below + {"X-Forwarded-For", "192.168.1.100"}, + {"Referer", "https://example.com/page"}, + {"Origin", "https://example.com"}, + {"Accept-Charset", "utf-8"}, + {"DNT", "1"}, +}; +static constexpr int kHeaderPoolSize = (int)(sizeof(kHeaders) / sizeof(kHeaders[0])); + +static GenRequest generateRequest(mt19937& rng, int idx) +{ + uniform_int_distribution methodDist(0, 1); + uniform_int_distribution headerDist(1, kHeaderPoolSize - 1); + uniform_int_distribution paramDist(0, 5); + uniform_int_distribution payloadDist(0, 2048); + + const bool isPost = (methodDist(rng) == 1); + const int numHeaders = headerDist(rng); // extra headers beyond Host + const int numParams = isPost ? 0 : paramDist(rng); + const int payloadSize = isPost ? payloadDist(rng) : 0; + + // Build URL + string url = "/api/resource/" + to_string(idx % 100); + if (numParams > 0) { + url += '?'; + for (int i = 0; i < numParams; ++i) { + if (i > 0) url += '&'; + url += 'p' + to_string(i) + "=v" + to_string((i * 37 + idx) % 1000); + } + } + + // Build header section (request line + headers, no trailing \r\n\r\n) + ostringstream oss; + oss << (isPost ? "POST" : "GET") << ' ' << url << " HTTP/1.1\r\n"; + + // Host is always first + oss << "Host: " << kHeaders[0].second << "\r\n"; + int added = 1; + for (int i = 1; i < kHeaderPoolSize && added <= numHeaders; ++i, ++added) { + oss << kHeaders[i].first << ": " << kHeaders[i].second; + if (i == 9) oss << to_string(idx); // make X-Request-Id unique + oss << "\r\n"; + } + if (isPost) { + oss << "Content-Length: " << payloadSize << "\r\n"; + oss << "Content-Type: application/json\r\n"; + } + + const int totalHeaders = added + (isPost ? 2 : 0); + + return { + oss.str(), + url, + isPost ? "POST" : "GET", + totalHeaders, + numParams, + payloadSize + }; +} + +// ─── Timing helper ──────────────────────────────────────────────────────────── + +static inline Nanos now_ns() +{ + return duration_cast( + high_resolution_clock::now().time_since_epoch()).count(); +} + +// ─── Main ───────────────────────────────────────────────────────────────────── + +int main(int argc, char* argv[]) +{ + const string csvPath = (argc > 1) ? argv[1] : "results-performance.csv"; + + constexpr int NUM_REQUESTS = 500; + constexpr int NUM_ITERS = 500; + + // ── Generate requests with a fixed seed for reproducibility ────────────── + mt19937 rng(42); + vector requests; + requests.reserve(NUM_REQUESTS); + for (int i = 0; i < NUM_REQUESTS; ++i) + requests.push_back(generateRequest(rng, i)); + + // ── Warmup – 10 passes to populate CPU caches ───────────────────────────── + for (int w = 0; w < 10; ++w) { + for (const auto& req : requests) { + { RequestHeader_t m; new_parseRequestHeaders(req.headerSection, m); } + { unordered_map m; legacy_parseRequestHeaders(req.headerSection, m); } + { URLParamMap_t m; new_parseGETParameter(req.url, m); } + { unordered_map m; legacy_parseGETParameter(req.url, m); } + } + } + + // ── Per-request benchmark results ───────────────────────────────────────── + struct Result { + Nanos nh_avg, nh_min, nh_max; // new header parsing + Nanos lh_avg, lh_min, lh_max; // legacy header parsing + Nanos np_avg, np_min, np_max; // new GET-param parsing + Nanos lp_avg, lp_min, lp_max; // legacy GET-param parsing + }; + vector results(NUM_REQUESTS); + + for (int r = 0; r < NUM_REQUESTS; ++r) { + const auto& req = requests[r]; + vector nh(NUM_ITERS), lh(NUM_ITERS), np(NUM_ITERS), lp(NUM_ITERS); + + for (int it = 0; it < NUM_ITERS; ++it) { + RequestHeader_t map; + Nanos t0 = now_ns(); + new_parseRequestHeaders(req.headerSection, map); + nh[it] = now_ns() - t0; + } + for (int it = 0; it < NUM_ITERS; ++it) { + unordered_map map; + Nanos t0 = now_ns(); + legacy_parseRequestHeaders(req.headerSection, map); + lh[it] = now_ns() - t0; + } + for (int it = 0; it < NUM_ITERS; ++it) { + URLParamMap_t map; + Nanos t0 = now_ns(); + new_parseGETParameter(req.url, map); + np[it] = now_ns() - t0; + } + for (int it = 0; it < NUM_ITERS; ++it) { + unordered_map map; + Nanos t0 = now_ns(); + legacy_parseGETParameter(req.url, map); + lp[it] = now_ns() - t0; + } + + auto stats = [](vector& v, Nanos& avg, Nanos& mn, Nanos& mx) { + sort(v.begin(), v.end()); + mn = v.front(); + mx = v.back(); + avg = accumulate(v.begin(), v.end(), Nanos{0}) / static_cast(v.size()); + }; + stats(nh, results[r].nh_avg, results[r].nh_min, results[r].nh_max); + stats(lh, results[r].lh_avg, results[r].lh_min, results[r].lh_max); + stats(np, results[r].np_avg, results[r].np_min, results[r].np_max); + stats(lp, results[r].lp_avg, results[r].lp_min, results[r].lp_max); + } + + // ── Write CSV ───────────────────────────────────────────────────────────── + ofstream csv(csvPath); + if (!csv) { + cerr << "Error: cannot open output file: " << csvPath << "\n"; + return 1; + } + + csv << "request_idx,method,header_count,url_param_count,payload_size," + "new_header_avg_ns,new_header_min_ns,new_header_max_ns," + "legacy_header_avg_ns,legacy_header_min_ns,legacy_header_max_ns," + "header_speedup_x," + "new_getparam_avg_ns,new_getparam_min_ns,new_getparam_max_ns," + "legacy_getparam_avg_ns,legacy_getparam_min_ns,legacy_getparam_max_ns," + "getparam_speedup_x\n"; + + for (int r = 0; r < NUM_REQUESTS; ++r) { + const auto& req = requests[r]; + const auto& res = results[r]; + + const double header_speedup = (res.nh_avg > 0) + ? static_cast(res.lh_avg) / res.nh_avg : 0.0; + const double param_speedup = (res.np_avg > 0) + ? static_cast(res.lp_avg) / res.np_avg : 0.0; + + csv << r << ',' + << req.method << ',' + << req.headerCount << ',' + << req.urlParamCount << ',' + << req.payloadSize << ',' + << res.nh_avg << ',' + << res.nh_min << ',' + << res.nh_max << ',' + << res.lh_avg << ',' + << res.lh_min << ',' + << res.lh_max << ',' + << fixed << setprecision(2) << header_speedup << ',' + << res.np_avg << ',' + << res.np_min << ',' + << res.np_max << ',' + << res.lp_avg << ',' + << res.lp_min << ',' + << res.lp_max << ',' + << param_speedup << '\n'; + } + csv.close(); + + // ── Print summary to stdout ──────────────────────────────────────────────── + Nanos sum_nh = 0, sum_lh = 0, sum_np = 0, sum_lp = 0; + for (int r = 0; r < NUM_REQUESTS; ++r) { + sum_nh += results[r].nh_avg; + sum_lh += results[r].lh_avg; + sum_np += results[r].np_avg; + sum_lp += results[r].lp_avg; + } + + cout << fixed << setprecision(2); + cout << "Performance results written to: " << csvPath << "\n\n"; + cout << "Summary over " << NUM_REQUESTS << " requests x " << NUM_ITERS << " iterations:\n"; + cout << " Header parsing: new=" << sum_nh / 1000 << " µs total" + << " legacy=" << sum_lh / 1000 << " µs total" + << " speedup=" << (sum_nh > 0 ? static_cast(sum_lh) / sum_nh : 0.0) << "x\n"; + cout << " GET-param parsing: new=" << sum_np / 1000 << " µs total" + << " legacy=" << sum_lp / 1000 << " µs total" + << " speedup=" << (sum_np > 0 ? static_cast(sum_lp) / sum_np : 0.0) << "x\n"; + + return 0; +} From ef5f8fb0ee967ea14d7e755200d69e0d529c9740 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Jul 2026 09:10:59 +0000 Subject: [PATCH 4/7] test: address code review findings in benchmark tests - Use chrono::nanoseconds::rep for Nanos type alias - Replace C-style sizeof casts with static_cast - Add thread-safety comment to global tracking variables - Fix median() for even-length vectors (average two central elements) --- test/performance/http-parser/test-parser-memory.cpp | 12 ++++++++++-- .../http-parser/test-parser-performance.cpp | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/test/performance/http-parser/test-parser-memory.cpp b/test/performance/http-parser/test-parser-memory.cpp index 05bc5c4..90cd5b9 100644 --- a/test/performance/http-parser/test-parser-memory.cpp +++ b/test/performance/http-parser/test-parser-memory.cpp @@ -22,6 +22,9 @@ #include // ─── Allocation tracker (must appear before any other includes) ─────────────── +// NOTE: g_tracking / g_alloc_count / g_alloc_bytes are intentionally not +// thread-safe. This benchmark is strictly single-threaded; no synchronisation +// primitives are needed or added here. static bool g_tracking = false; static size_t g_alloc_count = 0; static size_t g_alloc_bytes = 0; @@ -188,7 +191,7 @@ static const pair kHeaders[] = { {"Accept-Charset", "utf-8"}, {"DNT", "1"}, }; -static constexpr int kHeaderPoolSize = (int)(sizeof(kHeaders) / sizeof(kHeaders[0])); +static constexpr int kHeaderPoolSize = static_cast(sizeof(kHeaders) / sizeof(kHeaders[0])); static GenRequest generateRequest(mt19937& rng, int idx) { @@ -236,11 +239,16 @@ static GenRequest generateRequest(mt19937& rng, int idx) } // ─── Median helper ──────────────────────────────────────────────────────────── +// For even-length vectors the two central elements are averaged. template static T median(vector& v) { sort(v.begin(), v.end()); - return v[v.size() / 2]; + const size_t n = v.size(); + if (n == 0) return T{}; + if (n % 2 == 0) + return (v[n / 2 - 1] + v[n / 2]) / 2; + return v[n / 2]; } // ─── Main ───────────────────────────────────────────────────────────────────── diff --git a/test/performance/http-parser/test-parser-performance.cpp b/test/performance/http-parser/test-parser-performance.cpp index d45c023..8e7f278 100644 --- a/test/performance/http-parser/test-parser-performance.cpp +++ b/test/performance/http-parser/test-parser-performance.cpp @@ -33,7 +33,7 @@ using namespace std; using namespace chrono; -using Nanos = long long; +using Nanos = chrono::nanoseconds::rep; // ─── Legacy (pre-optimisation) implementations ─────────────────────────────── @@ -156,7 +156,7 @@ static const pair kHeaders[] = { {"Accept-Charset", "utf-8"}, {"DNT", "1"}, }; -static constexpr int kHeaderPoolSize = (int)(sizeof(kHeaders) / sizeof(kHeaders[0])); +static constexpr int kHeaderPoolSize = static_cast(sizeof(kHeaders) / sizeof(kHeaders[0])); static GenRequest generateRequest(mt19937& rng, int idx) { From 6a4666eab2c3f92876b39f3e21153ee2de1601f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Jul 2026 11:42:17 +0000 Subject: [PATCH 5/7] feat: add legacy C++11 HTTP parser files and USE_LEGACY_CPP11 cmake option --- CMakeLists.txt | 16 +- lib/http/CMakeLists.txt | 17 ++- lib/http/httpconstants-cpp11.hpp | 38 +++++ lib/http/httpparser-cpp11.cpp | 249 +++++++++++++++++++++++++++++++ lib/http/httpparser-cpp11.hpp | 153 +++++++++++++++++++ 5 files changed, 469 insertions(+), 4 deletions(-) create mode 100644 lib/http/httpconstants-cpp11.hpp create mode 100644 lib/http/httpparser-cpp11.cpp create mode 100644 lib/http/httpparser-cpp11.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ea15537..4bd77bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,11 +36,23 @@ if ( DEFINED JAVA_BACKEND ) endif() # set g++ compiler flags +# USE_LEGACY_CPP11: when ON the http library is compiled with -std=c++11 (legacy parser); +# the rest of the project also uses c++11. Default is c++23. +# Enable with: cmake -DUSE_LEGACY_CPP11=ON ... +option(USE_LEGACY_CPP11 "Build using the legacy C++11 HTTP parser implementation" OFF) +if(USE_LEGACY_CPP11) + set(HTTP_CXX_STD "-std=c++11") + add_compile_definitions(USE_LEGACY_CPP11) + message(STATUS "USE_LEGACY_CPP11=ON: compiling with -std=c++11 (legacy HTTP parser)") +else() + set(HTTP_CXX_STD "-std=c++23") +endif() + if ( DEFINED DEBUG_BUILD ) add_compile_definitions(DEBUG_BUILD) - set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread -std=c++23 -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -fwrapv -rdynamic -fno-elide-constructors") + set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread ${HTTP_CXX_STD} -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -fwrapv -rdynamic -fno-elide-constructors") else() - set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread -O3 -fstack-protector-strong -std=c++23 -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -DNDEBUG -fwrapv -fno-elide-constructors") + set(CMAKE_CXX_FLAGS "-g -fPIC -Wall -pthread -O3 -fstack-protector-strong ${HTTP_CXX_STD} -Wno-unused-result -Wsign-compare -Wformat -Werror=format-security -DNDEBUG -fwrapv -fno-elide-constructors") endif() # set boost specs diff --git a/lib/http/CMakeLists.txt b/lib/http/CMakeLists.txt index 21ccf88..925aeca 100644 --- a/lib/http/CMakeLists.txt +++ b/lib/http/CMakeLists.txt @@ -1,5 +1,14 @@ -# add source dir -aux_source_directory(. SRC_LIST_LIBHTTP) +# compile-time option: build with legacy C++11 HTTP parser instead of C++23 +# Enable with: cmake -DUSE_LEGACY_CPP11=ON ... +option(USE_LEGACY_CPP11 "Build using the legacy C++11 HTTP parser implementation" OFF) + +if(USE_LEGACY_CPP11) + # C++11 sources: legacy destructive-split / no string_view implementation + set(SRC_LIST_LIBHTTP httpparser-cpp11.cpp httpgenerator.cpp) +else() + # C++23 sources: optimised ispanstream / string_view / transparent-map implementation + set(SRC_LIST_LIBHTTP httpparser.cpp httpgenerator.cpp) +endif() # add library add_library(httpparser STATIC ${SRC_LIST_LIBHTTP}) @@ -9,6 +18,7 @@ add_custom_target( httpparserheader SOURCES ./httpparser.hpp + ./httpparser-cpp11.hpp ./httpgenerator.hpp ) @@ -22,6 +32,9 @@ install( install( FILES ./httpparser.hpp + ./httpparser-cpp11.hpp ./httpgenerator.hpp + ./httpconstants.hpp + ./httpconstants-cpp11.hpp DESTINATION /usr/local/include ) diff --git a/lib/http/httpconstants-cpp11.hpp b/lib/http/httpconstants-cpp11.hpp new file mode 100644 index 0000000..4a9cd88 --- /dev/null +++ b/lib/http/httpconstants-cpp11.hpp @@ -0,0 +1,38 @@ +#pragma once + +//- Legacy C++11 compatible constants header. +//- Functionally identical to httpconstants.hpp; usable with -std=c++11 or later. + +#include +#include +#include + +//- constant expressions +constexpr uint16_t HTTP_VERSION_UNKNOWN = 0; +constexpr uint16_t HTTP_VERSION_1_1 = 1; + +constexpr uint16_t HTTP_METHOD_OTHER = 0; +constexpr uint16_t HTTP_METHOD_GET = 1; +constexpr uint16_t HTTP_METHOD_POST = 2; + +constexpr uint16_t HTTP_POST_MAX_CONTENT_LENGTH = 2048; + +constexpr uint16_t URL_PARAM_NOT_FOUND_ERROR = 10; + +//- constant expressions (error) +constexpr uint16_t HTTP_ERROR_PARSE_BUFFER_EXCEEDED = 10; //- currently not implemented +constexpr uint16_t HTTP_ERROR_BAD_REQUEST = 400; + +//- constant strings +static const std::string HTTP_1_1_END_MARKER("\r\n\r\n"); +static const std::string HTTP_HEADER_CONTENT_LENGTH("Content-Length"); + +//- constant multidimensional +static const std::vector HTTPHeaderAllowed //- currently not implemented +{ + "Host", + "Transfer-Encoding", + "If-None-Match", + "Content-Type", + HTTP_HEADER_CONTENT_LENGTH +}; diff --git a/lib/http/httpparser-cpp11.cpp b/lib/http/httpparser-cpp11.cpp new file mode 100644 index 0000000..a7fe469 --- /dev/null +++ b/lib/http/httpparser-cpp11.cpp @@ -0,0 +1,249 @@ +#include "httpparser-cpp11.hpp" +#include "httpconstants-cpp11.hpp" + +using namespace std; + + +HTTPParser::HTTPParser(const uint16_t BufferSize) : + _RequestCountGet(0), + _RequestCountPost(0), + _RequestParseError(0), + _POSTWaitContentLength(false), + _POSTContentLength(0), + _HTTPRequestBuffer("") +{ + _HTTPRequestBuffer.reserve(BufferSize); + _HTTPRequestBufferMax = BufferSize; +} + +HTTPParser::~HTTPParser() +{ +} + +void HTTPParser::appendBuffer(const char* BufferRef, const uint16_t RecvBytes) +{ + if (_HTTPRequestBuffer.length()+RecvBytes > _HTTPRequestBufferMax) { + return; + } + + _HTTPRequestBuffer.append(BufferRef, RecvBytes); + + //- on incomplete (single) POST request + if (_POSTWaitContentLength == true && _HTTPRequestBuffer.length() >= _POSTContentLength) { + _RequestProperties.Payload = _HTTPRequestBuffer.substr(0, _POSTContentLength); + _HTTPRequestBuffer.erase(0, _POSTContentLength); + + _Requests.push_back(_RequestProperties); + + _POSTWaitContentLength = false; + } + else { + //- reset _SplittedRequests vector + _SplittedRequests.clear(); + + //- only process on minimum of 1 http request (end marker found) + const size_t EndMarkerFound = _HTTPRequestBuffer.find(HTTP_1_1_END_MARKER); + + if (EndMarkerFound != string::npos) { + _processRequests(); + } + } +} + +const RequestsMap_t& HTTPParser::getRequests() const +{ + return _Requests; +} + +RequestsMapPtr_t HTTPParser::getRequestsPtr() +{ + return &_Requests; +} + +inline void HTTPParser::_processRequests() +{ + //- split requests into _SplittedRequests vector + StringHelper::split(_HTTPRequestBuffer, HTTP_1_1_END_MARKER, _SplittedRequests); + + //- iterate over splitted requests + for(size_t i=0; i<_SplittedRequests.size(); ++i) { + if (_processRequestProperties(i) == false) { + _RequestParseError = HTTP_ERROR_BAD_REQUEST; + break; + } + } +} + +inline bool HTTPParser::_processRequestProperties(const size_t Index) +{ + //- get request ref at vector index + string &Request = _SplittedRequests.at(Index); + + //- on empty request return + if (Request.empty()) { return false; } + + //- init unparsed base properties with default values (C++11 compatible) + _RequestProperties.HTTPVersion = HTTP_VERSION_UNKNOWN; + _RequestProperties.HTTPMethod = HTTP_METHOD_OTHER; + _RequestProperties.URL = "/"; + _RequestProperties.Payload.clear(); + _RequestProperties.RequestHeaders.clear(); + _RequestProperties.URLParams.clear(); + + //- parse base properties + if (_parseRequestProperties(Request, _RequestProperties) == false) { return false; } + + //- only process HTTP/1.1 requests + if (_RequestProperties.HTTPVersion != HTTP_VERSION_1_1) { return false; } + + //- if not GET || POST method, return + if (_RequestProperties.HTTPMethod == HTTP_METHOD_OTHER) { return false; } + + //- parse request headers + _parseRequestHeaders(Request, _RequestProperties.RequestHeaders); + + //- GET request + if (_RequestProperties.HTTPMethod == HTTP_METHOD_GET) { + //- parse GET parameters + _parseGETParameter(_RequestProperties.URL, _RequestProperties.URLParams); + + //- add request to requests map + _Requests.push_back(_RequestProperties); + } + + //- POST request + else if (_RequestProperties.HTTPMethod == HTTP_METHOD_POST) { + + //- if request does not contain content-length header + if (_RequestProperties.RequestHeaders.find(HTTP_HEADER_CONTENT_LENGTH) == _RequestProperties.RequestHeaders.end()) { + return false; + } + + //- if content-length header contains non-digits + if (StringHelper::is_digits(_RequestProperties.RequestHeaders.at(HTTP_HEADER_CONTENT_LENGTH)) == false) { + return false; + } + + _POSTContentLength = stoi(_RequestProperties.RequestHeaders.at(HTTP_HEADER_CONTENT_LENGTH)); + + //- if content-length exeeds maximum + if (_POSTContentLength > HTTP_POST_MAX_CONTENT_LENGTH) { + return false; + } + + //- on single HTTP POST: payload after endmarker in _HTTPRequestBuffer + if (_SplittedRequests.size() == 1) { + //- content length bytes already in buffer + if (_HTTPRequestBuffer.length() >= _POSTContentLength) { + _RequestProperties.Payload = _HTTPRequestBuffer.substr(0, _POSTContentLength); + _HTTPRequestBuffer.erase(0, _POSTContentLength); + + //- add request to requests map + _Requests.push_back(_RequestProperties); + + } + else { + //- set flag to wait until content-length reached + _POSTWaitContentLength = true; + } + } + //- otherwise payload in next splitted message + else if (_SplittedRequests.size() > Index) { + string &NextRequest = _SplittedRequests.at(Index+1); + if (NextRequest.length() >= _POSTContentLength) { + _RequestProperties.Payload = NextRequest.substr(0, _POSTContentLength); + NextRequest.erase(0, _POSTContentLength); + //- add request to requests map + _Requests.push_back(_RequestProperties); + } + else { + return false; + } + } + } + return true; +} + +inline bool HTTPParser::_parseRequestProperties(const string& Request, const RequestPropertiesRef_t ResultBaseProps) +{ + //- find first line endline + size_t StartPos = Request.find("\r\n"); + + //-> if no headers (no \r\n), set start pos to end of string + if (StartPos == string::npos) { + StartPos = Request.length(); + } + + //- get base request properties + vector SplitResult; + StringHelper::rsplit(Request, StartPos, " ", SplitResult); + + //- on invalid vector size (!=3) abort + if (SplitResult.size() != 3) { return false; } + + if (SplitResult.at(0).find("HTTP/1.1") != string::npos) { + ResultBaseProps.HTTPVersion = HTTP_VERSION_1_1; + } + + if (SplitResult.at(2).find("GET") != string::npos) { + ResultBaseProps.HTTPMethod = HTTP_METHOD_GET; + } + else if (SplitResult.at(2).find("POST") != string::npos) { + ResultBaseProps.HTTPMethod = HTTP_METHOD_POST; + } + + ResultBaseProps.URL = SplitResult.at(1); + + return true; +} + +inline void HTTPParser::_parseRequestHeaders(const string& RequestIn, RequestHeaderRef_t ResultRef) +{ + //- copy request to allow destructive split + string Request = RequestIn; + + //- split header section into individual lines + vector Lines; + StringHelper::split(Request, "\r\n", Lines); + Lines.push_back(Request); //- push remainder after last \r\n + + for (auto& Line : Lines) { + vector HeaderPair; + StringHelper::rsplit(Line, Line.length(), ": ", HeaderPair); + if (HeaderPair.size() == 2 && + !HeaderPair[0].empty() && + !HeaderPair[1].empty()) + { + ResultRef.emplace(HeaderPair[1], HeaderPair[0]); //- key, value + } + } +} + +inline void HTTPParser::_parseGETParameter(const string& RequestURL, URLParamMapRef_t ResultRef) +{ + //- only process on init character "?" found + const size_t URLParamsStartPos = RequestURL.find("?"); + + if (URLParamsStartPos != string::npos && RequestURL.length() > URLParamsStartPos) { + + //- copy params substring (no string_view in C++11) + string URLParamsPart = RequestURL.substr(URLParamsStartPos + 1); + + vector ParamValuePairs; + StringHelper::split(URLParamsPart, "&", ParamValuePairs); + if (!URLParamsPart.empty()) ParamValuePairs.push_back(URLParamsPart); + + //- loop over param-value pairs + for (auto& ParamValuePair : ParamValuePairs) { + + const size_t PVPDelimiterPos = ParamValuePair.find("="); + + if (PVPDelimiterPos != string::npos && PVPDelimiterPos != 0 && ParamValuePair.length() > PVPDelimiterPos) { + ResultRef.emplace( + ParamValuePair.substr(0, PVPDelimiterPos), + ParamValuePair.substr(PVPDelimiterPos + 1) + ); + } + } + } +} diff --git a/lib/http/httpparser-cpp11.hpp b/lib/http/httpparser-cpp11.hpp new file mode 100644 index 0000000..152e577 --- /dev/null +++ b/lib/http/httpparser-cpp11.hpp @@ -0,0 +1,153 @@ +#pragma once + +//- Legacy C++11 compatible HTTP parser header. +//- Drop-in replacement for httpparser.hpp when targeting -std=c++11 or later. +//- Does not use string_view (C++17), span (C++20), or ispanstream (C++23). +//- Transparent unordered_map lookup (is_transparent / equal_to<>) is not used; +//- map key lookups construct a temporary std::string as in pre-C++14 code. + +#include +#include +#include +#include +#include +#include + +using namespace std; + +using RequestHeader_t = unordered_map; +using RequestHeaderRef_t = RequestHeader_t&; + +using URLParamMap_t = unordered_map; +using URLParamMapRef_t = URLParamMap_t&; + +struct RequestProperties_t +{ + uint16_t HTTPVersion; + uint16_t HTTPMethod; + RequestHeader_t RequestHeaders; + string URL; + string Payload; + URLParamMap_t URLParams; +}; + +using RequestPropertiesRef_t = RequestProperties_t&; + +using RequestsMap_t = vector; +using RequestsMapPtr_t = RequestsMap_t*; + + +class HTTPParser +{ + +public: + + HTTPParser(const uint16_t); + ~HTTPParser(); + + void appendBuffer(const char*, const uint16_t); + const RequestsMap_t& getRequests() const; + RequestsMapPtr_t getRequestsPtr(); + +private: + + void _processRequests(); + bool _processRequestProperties(const size_t); + + RequestHeader_t _RequestHeaders; + vector _SplittedRequests; + + size_t _RequestCountGet; + size_t _RequestCountPost; + + uint16_t _RequestParseError; + + bool _POSTWaitContentLength; + uint16_t _POSTContentLength; + + string _HTTPRequestBuffer; + + uint16_t _HTTPRequestBufferMax; + + RequestProperties_t _RequestProperties; + RequestsMap_t _Requests; + +protected: + + bool _parseRequestProperties(const string&, const RequestPropertiesRef_t); + void _parseRequestHeaders(const string&, RequestHeaderRef_t); + void _parseGETParameter(const string&, URLParamMapRef_t); +}; + + +class StringHelper { + +public: + + //- Destructive split: erases consumed tokens from StringRef in-place (used for buffer management) + static void split(string& StringRef, const string& Delimiter, vector& ResultRef) + { + size_t pos = StringRef.find(Delimiter); + while (pos != string::npos) { + ResultRef.push_back(StringRef.substr(0, pos)); + StringRef.erase(0, pos + Delimiter.size()); + pos = StringRef.find(Delimiter); + } + } + + static void rsplit(const string& String, size_t StartPos, const string& Delimiter, vector& ResultRef) + { + size_t FindPos = 0; + size_t FindPosLast = 0; + + //- guard ensures StartPos >= Delimiter.length() before the subtraction below + if (StartPos < Delimiter.length()) { + ResultRef.push_back(String.substr(0, StartPos)); + return; + } + + StartPos -= Delimiter.length(); //- safe: guarded by the check above + + while ((FindPos = String.rfind(Delimiter, StartPos)) != string::npos) { + + ResultRef.push_back(String.substr(FindPos + Delimiter.length(), StartPos - FindPos)); + + //- guard ensures FindPos >= Delimiter.length() before the subtraction below + if (FindPos < Delimiter.length()) { + FindPosLast = FindPos; + break; + } + + StartPos = FindPos - Delimiter.length(); //- safe: guarded by the check above + FindPosLast = FindPos; + } + + ResultRef.push_back(String.substr(0, FindPosLast)); + } + + static bool is_digits(const string& checkdigits) + { + return all_of(checkdigits.begin(), checkdigits.end(), ::isdigit); + } + +}; + +class JSON { + +public: + + static void URLParamsMap2JSON(URLParamMapRef_t URLParamsMap, string& JSONPayload) + { + JSONPayload = "{ \"payload\": {"; + + uint16_t i = 0; + for (const auto& ParamPair: URLParamsMap) { + JSONPayload += " \"" + ParamPair.first + "\": \"" + ParamPair.second + "\""; + if (i != URLParamsMap.size()-1) { + JSONPayload += ","; + } + ++i; + } + JSONPayload += " }}"; + } +}; From 784c0e46949c436a4ab4855390b15e635b5d0a59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:07:27 +0000 Subject: [PATCH 6/7] feat: use std::generator (co_yield/co_return) for HTTP parser string splitting --- CMakeLists.txt | 16 +++++++++++- lib/http/httpparser.cpp | 25 +++++-------------- lib/http/httpparser.hpp | 22 +++++++++++++--- .../http-parser/test-parser-memory.cpp | 22 ++++++---------- .../http-parser/test-parser-performance.cpp | 22 ++++++---------- 5 files changed, 53 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bd77bc..1f3d048 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,20 @@ # project settings cmake_minimum_required(VERSION 3.11) + +# The C++23 HTTP parser uses std::generator (), which requires GCC 14+. +# When USE_LEGACY_CPP11 is OFF (default) we auto-detect g++-14 and promote it to +# the project compiler. This must be done BEFORE project() to take effect. +option(USE_LEGACY_CPP11 "Build using the legacy C++11 HTTP parser implementation" OFF) +if(NOT USE_LEGACY_CPP11) + find_program(GXX14 g++-14) + if(GXX14) + set(CMAKE_CXX_COMPILER "${GXX14}" CACHE STRING "C++ compiler" FORCE) + message(STATUS "std::generator requires GCC 14+: using ${GXX14}") + else() + message(WARNING "g++-14 not found; std::generator may not be available. Install gcc-14 or pass -DCMAKE_CXX_COMPILER=g++-14.") + endif() +endif() + project(falcon-as) # do not print out warnings about unused variables @@ -39,7 +54,6 @@ endif() # USE_LEGACY_CPP11: when ON the http library is compiled with -std=c++11 (legacy parser); # the rest of the project also uses c++11. Default is c++23. # Enable with: cmake -DUSE_LEGACY_CPP11=ON ... -option(USE_LEGACY_CPP11 "Build using the legacy C++11 HTTP parser implementation" OFF) if(USE_LEGACY_CPP11) set(HTTP_CXX_STD "-std=c++11") add_compile_definitions(USE_LEGACY_CPP11) diff --git a/lib/http/httpparser.cpp b/lib/http/httpparser.cpp index 1175b0e..8b2f771 100644 --- a/lib/http/httpparser.cpp +++ b/lib/http/httpparser.cpp @@ -1,6 +1,5 @@ #include "httpparser.hpp" #include "httpconstants.hpp" -#include using namespace std; @@ -199,20 +198,12 @@ inline bool HTTPParser::_parseRequestProperties(string_view Request, const Reque inline void HTTPParser::_parseRequestHeaders(string_view Request, RequestHeaderRef_t ResultRef) { - //- wrap the raw buffer in a spanstream to parse lines without intermediate copies - ispanstream ss(span(Request.data(), Request.size())); - string line; - while (getline(ss, line, '\n')) { - if (!line.empty() && line.back() == '\r') line.pop_back(); - - //- require ": " (colon + space) to match original strict parsing behaviour + for (const auto line : StringHelper::linesOf(Request)) { const size_t colonSpace = line.find(": "); - if (colonSpace != string::npos && colonSpace > 0) { - string_view lv(line); - string_view key = lv.substr(0, colonSpace); - string_view value = lv.substr(colonSpace + 2); + if (colonSpace != string_view::npos && colonSpace > 0) { + const string_view value = line.substr(colonSpace + 2); if (!value.empty()) { - ResultRef.emplace(string(key), string(value)); + ResultRef.emplace(string(line.substr(0, colonSpace)), string(value)); } } } @@ -225,13 +216,9 @@ inline void HTTPParser::_parseGETParameter(string_view RequestURL, URLParamMapRe if (URLParamsStartPos != string_view::npos && RequestURL.length() > URLParamsStartPos) { - string_view URLParamsPart = RequestURL.substr(URLParamsStartPos + 1); - - vector ParamValuePairs; - StringHelper::split(URLParamsPart, "&", ParamValuePairs); + const string_view URLParamsPart = RequestURL.substr(URLParamsStartPos + 1); - //- loop over param-value pairs - for (const auto& ParamValuePair : ParamValuePairs) { + for (const auto ParamValuePair : StringHelper::splitView(URLParamsPart, "&")) { const size_t PVPDelimiterPos = ParamValuePair.find("="); diff --git a/lib/http/httpparser.hpp b/lib/http/httpparser.hpp index bbe9c81..142563e 100644 --- a/lib/http/httpparser.hpp +++ b/lib/http/httpparser.hpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace std; @@ -88,12 +89,25 @@ class StringHelper { public: - //- Non-destructive split: returns string_view slices into sv (zero heap allocation per token) - static void split(string_view sv, string_view delim, vector& out) + //- Non-destructive split: lazily yields string_view tokens (zero heap allocation per token) + static generator splitView(string_view sv, string_view delim) { for (size_t pos; (pos = sv.find(delim)) != sv.npos; sv.remove_prefix(pos + delim.size())) - out.push_back(sv.substr(0, pos)); - if (!sv.empty()) out.push_back(sv); + co_yield sv.substr(0, pos); + if (!sv.empty()) co_yield sv; + } + + //- Line iterator: lazily yields each CR-stripped line from sv (skips empty lines) + static generator linesOf(string_view sv) + { + while (!sv.empty()) { + const size_t pos = sv.find('\n'); + string_view line = (pos == sv.npos) ? sv : sv.substr(0, pos); + if (!line.empty() && line.back() == '\r') line.remove_suffix(1); + if (!line.empty()) co_yield line; + if (pos == sv.npos) break; + sv.remove_prefix(pos + 1); + } } //- Destructive split: erases consumed tokens from StringRef in-place (used for buffer management) diff --git a/test/performance/http-parser/test-parser-memory.cpp b/test/performance/http-parser/test-parser-memory.cpp index 90cd5b9..fccbaa2 100644 --- a/test/performance/http-parser/test-parser-memory.cpp +++ b/test/performance/http-parser/test-parser-memory.cpp @@ -1,7 +1,7 @@ // ───────────────────────────────────────────────────────────────────────────── // test-parser-memory.cpp // -// Heap-allocation benchmark: new (C++23 ispanstream / string_view) HTTP +// Heap-allocation benchmark: new (C++23 std::generator / string_view) HTTP // parser vs legacy (vector / destructive split) implementation. // // Global ::operator new / ::operator delete are replaced with tracking @@ -58,7 +58,6 @@ void operator delete[](void* p, size_t) noexcept { std::free(p); } #include #include #include -#include #include "../../../lib/http/httpparser.hpp" #include "../../../lib/http/httpconstants.hpp" @@ -129,17 +128,12 @@ static void new_parseRequestHeaders( string_view Request, RequestHeader_t& ResultRef) { - ispanstream ss(span(Request.data(), Request.size())); - string line; - while (getline(ss, line, '\n')) { - if (!line.empty() && line.back() == '\r') line.pop_back(); + for (const auto line : StringHelper::linesOf(Request)) { const size_t cs = line.find(": "); - if (cs != string::npos && cs > 0) { - string_view lv(line); - string_view key = lv.substr(0, cs); - string_view val = lv.substr(cs + 2); + if (cs != string_view::npos && cs > 0) { + const string_view val = line.substr(cs + 2); if (!val.empty()) - ResultRef.emplace(string(key), string(val)); + ResultRef.emplace(string(line.substr(0, cs)), string(val)); } } } @@ -150,10 +144,8 @@ static void new_parseGETParameter( { const size_t start = RequestURL.find('?'); if (start == string_view::npos || RequestURL.length() <= start) return; - string_view params = RequestURL.substr(start + 1); - vector pairs; - StringHelper::split(params, "&", pairs); - for (const auto& pair : pairs) { + const string_view params = RequestURL.substr(start + 1); + for (const auto pair : StringHelper::splitView(params, "&")) { const size_t eq = pair.find('='); if (eq != string_view::npos && eq != 0 && pair.length() > eq) { ResultRef.emplace( diff --git a/test/performance/http-parser/test-parser-performance.cpp b/test/performance/http-parser/test-parser-performance.cpp index 8e7f278..d60170c 100644 --- a/test/performance/http-parser/test-parser-performance.cpp +++ b/test/performance/http-parser/test-parser-performance.cpp @@ -1,7 +1,7 @@ // ───────────────────────────────────────────────────────────────────────────── // test-parser-performance.cpp // -// Wall-clock timing benchmark: new (C++23 ispanstream / string_view) HTTP +// Wall-clock timing benchmark: new (C++23 std::generator / string_view) HTTP // parser vs legacy (vector / destructive split) implementation. // // Generates NUM_REQUESTS (500) random valid HTTP requests with varying header @@ -26,7 +26,6 @@ #include #include #include -#include #include "../../../lib/http/httpparser.hpp" #include "../../../lib/http/httpconstants.hpp" @@ -93,17 +92,12 @@ static void new_parseRequestHeaders( string_view Request, RequestHeader_t& ResultRef) { - ispanstream ss(span(Request.data(), Request.size())); - string line; - while (getline(ss, line, '\n')) { - if (!line.empty() && line.back() == '\r') line.pop_back(); + for (const auto line : StringHelper::linesOf(Request)) { const size_t cs = line.find(": "); - if (cs != string::npos && cs > 0) { - string_view lv(line); - string_view key = lv.substr(0, cs); - string_view val = lv.substr(cs + 2); + if (cs != string_view::npos && cs > 0) { + const string_view val = line.substr(cs + 2); if (!val.empty()) - ResultRef.emplace(string(key), string(val)); + ResultRef.emplace(string(line.substr(0, cs)), string(val)); } } } @@ -115,10 +109,8 @@ static void new_parseGETParameter( { const size_t start = RequestURL.find('?'); if (start == string_view::npos || RequestURL.length() <= start) return; - string_view params = RequestURL.substr(start + 1); - vector pairs; - StringHelper::split(params, "&", pairs); - for (const auto& pair : pairs) { + const string_view params = RequestURL.substr(start + 1); + for (const auto pair : StringHelper::splitView(params, "&")) { const size_t eq = pair.find('='); if (eq != string_view::npos && eq != 0 && pair.length() > eq) { ResultRef.emplace( From c4713258f529dbf71800158b110115055934a33b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 30 Jul 2026 17:12:20 +0000 Subject: [PATCH 7/7] test: update performance and memory benchmark CSV results (post std::generator) --- .../http-parser/results-memory.csv | 501 ++++++++++++++++++ .../http-parser/results-performance.csv | 501 ++++++++++++++++++ 2 files changed, 1002 insertions(+) create mode 100644 test/performance/http-parser/results-memory.csv create mode 100644 test/performance/http-parser/results-performance.csv diff --git a/test/performance/http-parser/results-memory.csv b/test/performance/http-parser/results-memory.csv new file mode 100644 index 0000000..3d69e14 --- /dev/null +++ b/test/performance/http-parser/results-memory.csv @@ -0,0 +1,501 @@ +request_idx,method,header_count,url_param_count,payload_size,new_header_alloc_count,new_header_alloc_bytes,legacy_header_alloc_count,legacy_header_alloc_bytes,header_count_reduction,header_bytes_reduction_pct,new_getparam_alloc_count,new_getparam_alloc_bytes,legacy_getparam_alloc_count,legacy_getparam_alloc_bytes,getparam_count_reduction,getparam_bytes_reduction_pct +0,GET,13,5,0,19,1309,70,4571,51,71.4,7,640,11,1020,4,37.3 +1,GET,12,4,0,17,1217,64,4282,47,71.6,6,568,9,676,3,16.0 +2,POST,12,0,319,17,1209,64,4184,47,71.1,0,0,0,0,0,0.0 +3,GET,4,0,0,7,598,27,1800,20,66.8,0,0,0,0,0,0.0 +4,GET,8,5,0,12,904,46,3326,34,72.8,7,640,11,1020,4,37.3 +5,GET,10,0,0,14,1048,54,3692,40,71.6,0,0,0,0,0,0.0 +6,POST,13,0,42,18,1281,68,4421,50,71.0,0,0,0,0,0,0.0 +7,GET,15,4,0,22,1685,79,6216,57,72.9,6,568,9,676,3,16.0 +8,POST,17,0,435,25,1846,89,6652,64,72.2,0,0,0,0,0,0.0 +9,GET,4,5,0,7,598,27,1872,20,68.1,7,640,11,1020,4,37.3 +10,GET,10,1,0,14,1048,54,3710,40,71.8,3,352,3,216,0,-63.0 +11,POST,11,0,14,16,1137,60,3967,44,71.3,0,0,0,0,0,0.0 +12,GET,2,1,0,4,400,16,910,12,56.0,3,352,3,216,0,-63.0 +13,POST,12,0,819,17,1209,64,4188,47,71.1,0,0,0,0,0,0.0 +14,GET,2,1,0,4,400,16,910,12,56.0,3,352,3,216,0,-63.0 +15,POST,9,0,476,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +16,GET,3,4,0,6,526,23,1619,17,67.5,6,568,9,677,3,16.1 +17,POST,6,0,783,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +18,POST,17,0,1213,25,1846,89,6658,64,72.3,0,0,0,0,0,0.0 +19,GET,2,5,0,4,400,16,970,12,58.8,7,640,11,1021,4,37.3 +20,POST,13,0,349,18,1281,68,4427,50,71.1,0,0,0,0,0,0.0 +21,GET,2,0,0,4,400,16,896,12,55.4,0,0,0,0,0,0.0 +22,POST,17,0,1978,25,1846,89,6658,64,72.3,0,0,0,0,0,0.0 +23,POST,15,0,789,23,1702,82,6251,59,72.8,0,0,0,0,0,0.0 +24,GET,2,0,0,4,400,16,896,12,55.4,0,0,0,0,0,0.0 +25,GET,11,1,0,15,1120,58,3949,43,71.6,3,352,3,216,0,-63.0 +26,GET,11,0,0,15,1120,58,3935,43,71.5,0,0,0,0,0,0.0 +27,POST,10,0,1707,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +28,GET,4,5,0,7,598,27,1878,20,68.2,7,640,11,1022,4,37.4 +29,GET,5,1,0,9,688,33,2099,24,67.2,3,352,3,216,0,-63.0 +30,POST,14,0,638,21,1610,75,4954,54,67.5,0,0,0,0,0,0.0 +31,GET,9,1,0,13,976,50,3491,37,72.0,3,352,3,216,0,-63.0 +32,POST,11,0,378,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +33,GET,15,5,0,22,1685,79,6240,57,73.0,7,640,11,1022,4,37.4 +34,POST,10,0,1925,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +35,GET,14,5,0,21,1613,75,5032,54,67.9,7,640,11,1022,4,37.4 +36,POST,14,0,1888,21,1610,75,4956,54,67.5,0,0,0,0,0,0.0 +37,GET,3,3,0,6,526,23,1605,17,67.2,5,496,8,590,3,15.9 +38,GET,9,0,0,13,976,50,3477,37,71.9,0,0,0,0,0,0.0 +39,POST,8,0,1730,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +40,GET,12,1,0,17,1217,64,4244,47,71.3,3,352,3,216,0,-63.0 +41,POST,15,0,1202,23,1702,82,6253,59,72.8,0,0,0,0,0,0.0 +42,GET,15,1,0,22,1685,79,6178,57,72.7,3,352,3,216,0,-63.0 +43,POST,11,0,565,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +44,GET,6,4,0,10,760,37,2368,27,67.9,6,568,9,678,3,16.2 +45,GET,3,0,0,6,526,23,1561,17,66.3,0,0,0,0,0,0.0 +46,POST,9,0,1582,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +47,GET,4,1,0,7,598,27,1816,20,67.1,3,352,3,216,0,-63.0 +48,GET,2,4,0,4,400,16,956,12,58.2,6,568,9,678,3,16.2 +49,GET,11,4,0,15,1120,58,3995,43,72.0,6,568,9,678,3,16.2 +50,POST,15,0,1580,23,1702,82,6253,59,72.8,0,0,0,0,0,0.0 +51,POST,5,0,1897,9,687,33,2055,24,66.6,0,0,0,0,0,0.0 +52,GET,11,0,0,15,1120,58,3935,43,71.5,0,0,0,0,0,0.0 +53,POST,16,0,1741,24,1774,86,6474,62,72.6,0,0,0,0,0,0.0 +54,POST,10,0,678,15,1065,56,3748,41,71.6,0,0,0,0,0,0.0 +55,GET,2,2,0,4,400,16,924,12,56.7,4,424,5,360,1,-17.8 +56,GET,11,1,0,15,1120,58,3949,43,71.6,3,352,3,216,0,-63.0 +57,POST,14,0,1211,21,1610,75,4956,54,67.5,0,0,0,0,0,0.0 +58,POST,7,0,1817,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +59,POST,10,0,784,15,1065,56,3748,41,71.6,0,0,0,0,0,0.0 +60,GET,15,4,0,22,1685,79,6224,57,72.9,6,568,9,678,3,16.2 +61,POST,14,0,1478,21,1610,75,4956,54,67.5,0,0,0,0,0,0.0 +62,POST,7,0,1579,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +63,GET,8,0,0,12,904,46,3256,34,72.2,0,0,0,0,0,0.0 +64,POST,13,0,876,18,1281,68,4427,50,71.1,0,0,0,0,0,0.0 +65,GET,2,2,0,4,400,16,926,12,56.8,4,424,5,360,1,-17.8 +66,GET,4,0,0,7,598,27,1802,20,66.8,0,0,0,0,0,0.0 +67,POST,12,0,974,17,1209,64,4188,47,71.1,0,0,0,0,0,0.0 +68,GET,9,3,0,13,976,50,3523,37,72.3,5,496,8,591,3,16.1 +69,POST,16,0,285,24,1774,86,6472,62,72.6,0,0,0,0,0,0.0 +70,GET,10,2,0,14,1048,54,3726,40,71.9,4,424,5,360,1,-17.8 +71,POST,14,0,416,21,1610,75,4954,54,67.5,0,0,0,0,0,0.0 +72,GET,15,0,0,22,1685,79,6164,57,72.7,0,0,0,0,0,0.0 +73,POST,8,0,1423,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +74,GET,14,5,0,21,1613,75,5034,54,68.0,7,640,11,1023,4,37.4 +75,POST,15,0,605,23,1702,82,6251,59,72.8,0,0,0,0,0,0.0 +76,POST,5,0,1785,9,687,33,2055,24,66.6,0,0,0,0,0,0.0 +77,GET,13,1,0,19,1309,70,4517,51,71.0,3,352,3,216,0,-63.0 +78,GET,7,5,0,11,832,42,3123,31,73.4,7,640,11,1023,4,37.4 +79,POST,11,0,664,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +80,POST,5,0,1836,9,687,33,2055,24,66.6,0,0,0,0,0,0.0 +81,GET,6,5,0,10,760,37,2386,27,68.1,7,640,11,1023,4,37.4 +82,GET,5,1,0,9,688,33,2099,24,67.2,3,352,3,216,0,-63.0 +83,POST,9,0,1,14,993,52,3533,38,71.9,0,0,0,0,0,0.0 +84,POST,8,0,1763,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +85,GET,2,0,0,4,400,16,896,12,55.4,0,0,0,0,0,0.0 +86,POST,11,0,855,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +87,GET,5,4,0,9,688,33,2147,24,68.0,6,568,9,679,3,16.3 +88,GET,5,2,0,9,688,33,2115,24,67.5,4,424,5,360,1,-17.8 +89,GET,15,1,0,22,1685,79,6178,57,72.7,3,352,3,216,0,-63.0 +90,GET,5,3,0,9,688,33,2131,24,67.7,5,496,8,591,3,16.1 +91,POST,13,0,827,18,1281,68,4427,50,71.1,0,0,0,0,0,0.0 +92,GET,2,5,0,4,400,16,974,12,58.9,7,640,11,1023,4,37.4 +93,GET,15,1,0,22,1685,79,6178,57,72.7,3,352,3,216,0,-63.0 +94,GET,11,2,0,15,1120,58,3965,43,71.8,4,424,5,360,1,-17.8 +95,POST,8,0,303,13,921,48,3312,35,72.2,0,0,0,0,0,0.0 +96,GET,15,0,0,22,1685,79,6164,57,72.7,0,0,0,0,0,0.0 +97,GET,10,5,0,14,1048,54,3774,40,72.2,7,640,11,1023,4,37.4 +98,POST,9,0,105,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +99,GET,5,2,0,9,688,33,2115,24,67.5,4,424,5,360,1,-17.8 +100,POST,12,0,490,17,1209,64,4188,47,71.1,0,0,0,0,0,0.0 +101,POST,6,0,1087,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +102,GET,8,5,0,12,904,46,3334,34,72.9,7,640,11,1024,4,37.5 +103,POST,7,0,1214,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +104,POST,5,0,1560,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +105,GET,5,1,0,9,688,33,2099,24,67.2,3,352,3,216,0,-63.0 +106,POST,15,0,753,23,1702,82,6251,59,72.8,0,0,0,0,0,0.0 +107,GET,10,5,0,14,1048,54,3776,40,72.2,7,640,11,1024,4,37.5 +108,POST,9,0,1097,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +109,POST,5,0,1635,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +110,POST,6,0,657,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +111,POST,6,0,1425,10,759,37,2296,27,66.9,0,0,0,0,0,0.0 +112,GET,14,3,0,21,1613,75,5006,54,67.8,5,496,8,592,3,16.2 +113,GET,11,1,0,15,1120,58,3953,43,71.7,3,352,3,216,0,-63.0 +114,GET,11,3,0,15,1120,58,3985,43,71.9,5,496,8,592,3,16.2 +115,POST,7,0,714,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +116,POST,5,0,357,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +117,POST,13,0,814,18,1281,68,4429,50,71.1,0,0,0,0,0,0.0 +118,GET,9,5,0,13,976,50,3557,37,72.6,7,640,11,1024,4,37.5 +119,POST,5,0,1384,9,687,33,2055,24,66.6,0,0,0,0,0,0.0 +120,GET,12,0,0,17,1217,64,4232,47,71.2,0,0,0,0,0,0.0 +121,GET,14,3,0,21,1613,75,5006,54,67.8,5,496,8,592,3,16.2 +122,POST,13,0,528,18,1281,68,4429,50,71.1,0,0,0,0,0,0.0 +123,GET,11,1,0,15,1120,58,3953,43,71.7,3,352,3,216,0,-63.0 +124,POST,17,0,1137,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +125,POST,11,0,534,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +126,GET,15,0,0,22,1685,79,6166,57,72.7,0,0,0,0,0,0.0 +127,POST,16,0,1143,24,1774,86,6476,62,72.6,0,0,0,0,0,0.0 +128,POST,16,0,1297,24,1774,86,6476,62,72.6,0,0,0,0,0,0.0 +129,GET,6,1,0,10,760,37,2324,27,67.3,3,352,3,216,0,-63.0 +130,GET,11,4,0,15,1120,58,4001,43,72.0,6,568,9,680,3,16.5 +131,POST,16,0,1754,24,1774,86,6476,62,72.6,0,0,0,0,0,0.0 +132,POST,9,0,1597,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +133,POST,12,0,1743,17,1209,64,4192,47,71.2,0,0,0,0,0,0.0 +134,GET,15,0,0,22,1685,79,6166,57,72.7,0,0,0,0,0,0.0 +135,POST,16,0,1370,24,1774,86,6476,62,72.6,0,0,0,0,0,0.0 +136,POST,12,0,18,17,1209,64,4188,47,71.1,0,0,0,0,0,0.0 +137,GET,3,5,0,6,526,23,1641,17,67.9,7,640,11,1024,4,37.5 +138,POST,17,0,10,25,1846,89,6656,64,72.3,0,0,0,0,0,0.0 +139,GET,4,1,0,7,598,27,1818,20,67.1,3,352,3,216,0,-63.0 +140,POST,10,0,1417,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +141,GET,11,5,0,15,1120,58,4017,43,72.1,7,640,11,1024,4,37.5 +142,GET,4,4,0,7,598,27,1866,20,68.0,6,568,9,680,3,16.5 +143,GET,5,2,0,9,688,33,2117,24,67.5,4,424,5,360,1,-17.8 +144,GET,4,4,0,7,598,27,1866,20,68.0,6,568,9,680,3,16.5 +145,GET,11,4,0,15,1120,58,4001,43,72.0,6,568,9,680,3,16.5 +146,POST,14,0,1347,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +147,GET,9,3,0,13,976,50,3525,37,72.3,5,496,8,592,3,16.2 +148,GET,9,2,0,13,976,50,3509,37,72.2,4,424,5,360,1,-17.8 +149,POST,7,0,513,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +150,GET,10,5,0,14,1048,54,3778,40,72.3,7,640,11,1024,4,37.5 +151,POST,9,0,997,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +152,POST,16,0,1293,24,1774,86,6476,62,72.6,0,0,0,0,0,0.0 +153,GET,13,2,0,19,1309,70,4537,51,71.1,4,424,5,360,1,-17.8 +154,POST,13,0,1182,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +155,POST,10,0,1770,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +156,GET,5,4,0,9,688,33,2149,24,68.0,6,568,9,680,3,16.5 +157,GET,5,3,0,9,688,33,2133,24,67.7,5,496,8,592,3,16.2 +158,GET,12,3,0,17,1217,64,4280,47,71.6,5,496,8,592,3,16.2 +159,GET,4,5,0,7,598,27,1882,20,68.2,7,640,11,1024,4,37.5 +160,POST,10,0,1954,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +161,GET,14,5,0,21,1613,75,5038,54,68.0,7,640,11,1024,4,37.5 +162,GET,12,0,0,17,1217,64,4232,47,71.2,0,0,0,0,0,0.0 +163,POST,16,0,677,24,1774,86,6474,62,72.6,0,0,0,0,0,0.0 +164,GET,9,5,0,13,976,50,3557,37,72.6,7,640,11,1024,4,37.5 +165,POST,17,0,2008,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +166,POST,5,0,603,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +167,GET,7,1,0,11,832,42,3061,31,72.8,3,352,3,216,0,-63.0 +168,POST,7,0,649,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +169,GET,4,2,0,7,598,27,1834,20,67.4,4,424,5,360,1,-17.8 +170,POST,9,0,1918,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +171,POST,13,0,1905,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +172,POST,4,0,199,7,561,27,1644,20,65.9,0,0,0,0,0,0.0 +173,GET,10,4,0,14,1048,54,3762,40,72.1,6,568,9,680,3,16.5 +174,POST,9,0,287,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +175,GET,9,1,0,13,976,50,3493,37,72.1,3,352,3,216,0,-63.0 +176,POST,8,0,1517,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +177,POST,13,0,279,18,1281,68,4429,50,71.1,0,0,0,0,0,0.0 +178,POST,13,0,736,18,1281,68,4429,50,71.1,0,0,0,0,0,0.0 +179,POST,8,0,607,13,921,48,3312,35,72.2,0,0,0,0,0,0.0 +180,POST,9,0,1659,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +181,GET,14,3,0,21,1613,75,5006,54,67.8,5,496,8,592,3,16.2 +182,POST,5,0,1047,9,687,33,2055,24,66.6,0,0,0,0,0,0.0 +183,GET,9,3,0,13,976,50,3525,37,72.3,5,496,8,592,3,16.2 +184,POST,6,0,1331,10,759,37,2296,27,66.9,0,0,0,0,0,0.0 +185,GET,11,2,0,15,1120,58,3969,43,71.8,4,424,5,360,1,-17.8 +186,POST,4,0,1823,7,561,27,1646,20,65.9,0,0,0,0,0,0.0 +187,POST,8,0,56,13,921,48,3310,35,72.2,0,0,0,0,0,0.0 +188,GET,10,0,0,14,1048,54,3698,40,71.7,0,0,0,0,0,0.0 +189,GET,10,4,0,14,1048,54,3762,40,72.1,6,568,9,680,3,16.5 +190,GET,6,2,0,10,760,37,2340,27,67.5,4,424,5,360,1,-17.8 +191,GET,9,5,0,13,976,50,3557,37,72.6,7,640,11,1024,4,37.5 +192,GET,13,3,0,19,1309,70,4553,51,71.2,5,496,8,592,3,16.2 +193,POST,4,0,512,7,561,27,1644,20,65.9,0,0,0,0,0,0.0 +194,GET,2,4,0,4,400,16,960,12,58.3,6,568,9,680,3,16.5 +195,GET,7,3,0,11,832,42,3093,31,73.1,5,496,8,592,3,16.2 +196,GET,6,3,0,10,760,37,2356,27,67.7,5,496,8,592,3,16.2 +197,POST,14,0,556,21,1610,75,4956,54,67.5,0,0,0,0,0,0.0 +198,GET,15,3,0,22,1685,79,6214,57,72.9,5,496,8,592,3,16.2 +199,GET,3,5,0,6,526,23,1641,17,67.9,7,640,11,1024,4,37.5 +200,GET,4,3,0,7,598,27,1848,20,67.6,5,496,8,592,3,16.2 +201,GET,9,4,0,13,976,50,3539,37,72.4,6,568,9,680,3,16.5 +202,POST,5,0,1487,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +203,GET,15,5,0,22,1685,79,6244,57,73.0,7,640,11,1024,4,37.5 +204,POST,14,0,661,21,1610,75,4954,54,67.5,0,0,0,0,0,0.0 +205,GET,13,2,0,19,1309,70,4535,51,71.1,4,424,5,360,1,-17.8 +206,GET,8,2,0,12,904,46,3286,34,72.5,4,424,5,360,1,-17.8 +207,POST,5,0,514,9,687,33,2051,24,66.5,0,0,0,0,0,0.0 +208,GET,4,5,0,7,598,27,1880,20,68.2,7,640,11,1024,4,37.5 +209,GET,13,2,0,19,1309,70,4535,51,71.1,4,424,5,360,1,-17.8 +210,POST,13,0,837,18,1281,68,4429,50,71.1,0,0,0,0,0,0.0 +211,GET,4,5,0,7,598,27,1882,20,68.2,7,640,11,1024,4,37.5 +212,GET,8,1,0,12,904,46,3272,34,72.4,3,352,3,216,0,-63.0 +213,GET,9,0,0,13,976,50,3477,37,71.9,0,0,0,0,0,0.0 +214,POST,6,0,1352,10,759,37,2296,27,66.9,0,0,0,0,0,0.0 +215,POST,7,0,1307,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +216,POST,11,0,1511,16,1137,60,3971,44,71.4,0,0,0,0,0,0.0 +217,POST,11,0,892,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +218,POST,14,0,859,21,1610,75,4956,54,67.5,0,0,0,0,0,0.0 +219,GET,5,3,0,9,688,33,2133,24,67.7,5,496,8,592,3,16.2 +220,GET,4,4,0,7,598,27,1866,20,68.0,6,568,9,680,3,16.5 +221,GET,2,2,0,4,400,16,928,12,56.9,4,424,5,360,1,-17.8 +222,GET,3,0,0,6,526,23,1561,17,66.3,0,0,0,0,0,0.0 +223,GET,2,1,0,4,400,16,912,12,56.1,3,352,3,216,0,-63.0 +224,POST,17,0,1441,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +225,GET,8,0,0,12,904,46,3256,34,72.2,0,0,0,0,0,0.0 +226,GET,12,2,0,17,1217,64,4264,47,71.5,4,424,5,360,1,-17.8 +227,POST,10,0,709,15,1065,56,3748,41,71.6,0,0,0,0,0,0.0 +228,GET,8,2,0,12,904,46,3288,34,72.5,4,424,5,360,1,-17.8 +229,POST,9,0,98,14,993,52,3535,38,71.9,0,0,0,0,0,0.0 +230,POST,17,0,1301,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +231,POST,4,0,534,7,561,27,1644,20,65.9,0,0,0,0,0,0.0 +232,GET,2,3,0,4,400,16,944,12,57.6,5,496,8,592,3,16.2 +233,POST,11,0,1026,16,1137,60,3971,44,71.4,0,0,0,0,0,0.0 +234,POST,11,0,1349,16,1137,60,3971,44,71.4,0,0,0,0,0,0.0 +235,POST,6,0,1261,10,759,37,2296,27,66.9,0,0,0,0,0,0.0 +236,GET,15,3,0,22,1685,79,6214,57,72.9,5,496,8,592,3,16.2 +237,POST,4,0,1776,7,561,27,1646,20,65.9,0,0,0,0,0,0.0 +238,POST,12,0,1926,17,1209,64,4192,47,71.2,0,0,0,0,0,0.0 +239,POST,12,0,1387,17,1209,64,4192,47,71.2,0,0,0,0,0,0.0 +240,GET,10,3,0,14,1048,54,3746,40,72.0,5,496,8,592,3,16.2 +241,GET,8,4,0,12,904,46,3320,34,72.8,6,568,9,680,3,16.5 +242,POST,15,0,1929,23,1702,82,6255,59,72.8,0,0,0,0,0,0.0 +243,POST,9,0,1681,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +244,POST,13,0,1855,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +245,GET,4,1,0,7,598,27,1818,20,67.1,3,352,3,216,0,-63.0 +246,GET,5,0,0,9,688,33,2085,24,67.0,0,0,0,0,0,0.0 +247,GET,2,0,0,4,400,16,896,12,55.4,0,0,0,0,0,0.0 +248,GET,10,4,0,14,1048,54,3762,40,72.1,6,568,9,680,3,16.5 +249,GET,2,3,0,4,400,16,944,12,57.6,5,496,8,592,3,16.2 +250,GET,7,5,0,11,832,42,3125,31,73.4,7,640,11,1024,4,37.5 +251,POST,4,0,697,7,561,27,1644,20,65.9,0,0,0,0,0,0.0 +252,POST,7,0,577,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +253,GET,3,4,0,6,526,23,1625,17,67.6,6,568,9,680,3,16.5 +254,POST,8,0,1288,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +255,POST,16,0,80,24,1774,86,6472,62,72.6,0,0,0,0,0,0.0 +256,POST,9,0,1646,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +257,POST,7,0,1122,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +258,GET,7,4,0,11,832,42,3109,31,73.2,6,568,9,680,3,16.5 +259,POST,15,0,1180,23,1702,82,6255,59,72.8,0,0,0,0,0,0.0 +260,POST,14,0,845,21,1610,75,4956,54,67.5,0,0,0,0,0,0.0 +261,GET,7,1,0,11,832,42,3061,31,72.8,3,352,3,216,0,-63.0 +262,POST,12,0,698,17,1209,64,4190,47,71.1,0,0,0,0,0,0.0 +263,POST,17,0,1151,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +264,POST,7,0,879,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +265,POST,14,0,1516,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +266,POST,7,0,211,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +267,GET,14,3,0,21,1613,75,5006,54,67.8,5,496,8,592,3,16.2 +268,POST,10,0,1693,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +269,GET,6,1,0,10,760,37,2324,27,67.3,3,352,3,216,0,-63.0 +270,POST,5,0,797,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +271,GET,2,5,0,4,400,16,976,12,59.0,7,640,11,1024,4,37.5 +272,POST,15,0,187,23,1702,82,6253,59,72.8,0,0,0,0,0,0.0 +273,GET,6,5,0,10,760,37,2388,27,68.2,7,640,11,1024,4,37.5 +274,POST,13,0,1947,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +275,GET,10,2,0,14,1048,54,3730,40,71.9,4,424,5,360,1,-17.8 +276,POST,5,0,918,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +277,GET,6,3,0,10,760,37,2356,27,67.7,5,496,8,592,3,16.2 +278,GET,9,4,0,13,976,50,3541,37,72.4,6,568,9,680,3,16.5 +279,GET,12,5,0,17,1217,64,4312,47,71.8,7,640,11,1024,4,37.5 +280,POST,14,0,1617,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +281,GET,3,5,0,6,526,23,1641,17,67.9,7,640,11,1024,4,37.5 +282,GET,15,0,0,22,1685,79,6166,57,72.7,0,0,0,0,0,0.0 +283,POST,11,0,114,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +284,GET,12,5,0,17,1217,64,4312,47,71.8,7,640,11,1024,4,37.5 +285,POST,8,0,1446,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +286,GET,15,0,0,22,1685,79,6166,57,72.7,0,0,0,0,0,0.0 +287,POST,14,0,1714,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +288,POST,16,0,207,24,1774,86,6474,62,72.6,0,0,0,0,0,0.0 +289,POST,5,0,873,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +290,POST,7,0,149,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +291,GET,13,5,0,19,1309,70,4585,51,71.5,7,640,11,1024,4,37.5 +292,POST,6,0,166,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +293,POST,5,0,477,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +294,POST,12,0,766,17,1209,64,4190,47,71.1,0,0,0,0,0,0.0 +295,POST,9,0,1803,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +296,POST,7,0,1940,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +297,POST,17,0,1212,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +298,POST,8,0,770,13,921,48,3312,35,72.2,0,0,0,0,0,0.0 +299,POST,5,0,986,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +300,POST,9,0,1144,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +301,POST,9,0,509,14,993,52,3535,38,71.9,0,0,0,0,0,0.0 +302,POST,8,0,227,13,921,48,3310,35,72.2,0,0,0,0,0,0.0 +303,GET,8,1,0,12,904,46,3270,34,72.4,3,352,3,216,0,-63.0 +304,GET,7,2,0,11,832,42,3075,31,72.9,4,424,5,360,1,-17.8 +305,POST,4,0,1518,7,561,27,1644,20,65.9,0,0,0,0,0,0.0 +306,GET,12,0,0,17,1217,64,4230,47,71.2,0,0,0,0,0,0.0 +307,POST,13,0,1524,18,1281,68,4429,50,71.1,0,0,0,0,0,0.0 +308,POST,13,0,1195,18,1281,68,4429,50,71.1,0,0,0,0,0,0.0 +309,GET,15,2,0,22,1685,79,6196,57,72.8,4,424,5,360,1,-17.8 +310,GET,8,1,0,12,904,46,3272,34,72.4,3,352,3,216,0,-63.0 +311,GET,14,3,0,21,1613,75,5006,54,67.8,5,496,8,592,3,16.2 +312,GET,8,5,0,12,904,46,3336,34,72.9,7,640,11,1024,4,37.5 +313,POST,4,0,2003,7,561,27,1646,20,65.9,0,0,0,0,0,0.0 +314,POST,11,0,88,16,1137,60,3967,44,71.3,0,0,0,0,0,0.0 +315,GET,14,0,0,21,1613,75,4958,54,67.5,0,0,0,0,0,0.0 +316,POST,16,0,2034,24,1774,86,6476,62,72.6,0,0,0,0,0,0.0 +317,POST,5,0,518,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +318,POST,13,0,1986,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +319,GET,9,0,0,13,976,50,3477,37,71.9,0,0,0,0,0,0.0 +320,POST,7,0,1425,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +321,GET,8,5,0,12,904,46,3336,34,72.9,7,640,11,1024,4,37.5 +322,POST,13,0,1197,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +323,GET,14,4,0,21,1613,75,5022,54,67.9,6,568,9,680,3,16.5 +324,GET,14,1,0,21,1613,75,4974,54,67.6,3,352,3,216,0,-63.0 +325,POST,17,0,118,25,1846,89,6658,64,72.3,0,0,0,0,0,0.0 +326,POST,9,0,933,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +327,GET,10,2,0,14,1048,54,3730,40,71.9,4,424,5,360,1,-17.8 +328,GET,4,1,0,7,598,27,1818,20,67.1,3,352,3,216,0,-63.0 +329,POST,10,0,795,15,1065,56,3748,41,71.6,0,0,0,0,0,0.0 +330,GET,5,3,0,9,688,33,2133,24,67.7,5,496,8,592,3,16.2 +331,GET,3,2,0,6,526,23,1593,17,67.0,4,424,5,360,1,-17.8 +332,POST,7,0,2020,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +333,GET,11,0,0,15,1120,58,3937,43,71.6,0,0,0,0,0,0.0 +334,POST,7,0,634,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +335,GET,13,3,0,19,1309,70,4553,51,71.2,5,496,8,592,3,16.2 +336,POST,7,0,333,12,849,44,3089,32,72.5,0,0,0,0,0,0.0 +337,GET,14,0,0,21,1613,75,4958,54,67.5,0,0,0,0,0,0.0 +338,POST,17,0,1946,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +339,GET,12,3,0,17,1217,64,4280,47,71.6,5,496,8,592,3,16.2 +340,POST,16,0,856,24,1774,86,6474,62,72.6,0,0,0,0,0,0.0 +341,GET,15,5,0,22,1685,79,6246,57,73.0,7,640,11,1024,4,37.5 +342,POST,11,0,92,16,1137,60,3967,44,71.3,0,0,0,0,0,0.0 +343,GET,2,2,0,4,400,16,928,12,56.9,4,424,5,360,1,-17.8 +344,GET,12,4,0,17,1217,64,4296,47,71.7,6,568,9,680,3,16.5 +345,GET,15,5,0,22,1685,79,6246,57,73.0,7,640,11,1024,4,37.5 +346,GET,7,3,0,11,832,42,3093,31,73.1,5,496,8,592,3,16.2 +347,POST,9,0,805,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +348,POST,15,0,1725,23,1702,82,6255,59,72.8,0,0,0,0,0,0.0 +349,POST,15,0,130,23,1702,82,6253,59,72.8,0,0,0,0,0,0.0 +350,GET,2,2,0,4,400,16,928,12,56.9,4,424,5,360,1,-17.8 +351,GET,5,0,0,9,688,33,2085,24,67.0,0,0,0,0,0,0.0 +352,GET,3,5,0,6,526,23,1641,17,67.9,7,640,11,1024,4,37.5 +353,POST,15,0,1094,23,1702,82,6255,59,72.8,0,0,0,0,0,0.0 +354,POST,14,0,2042,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +355,POST,11,0,1198,16,1137,60,3971,44,71.4,0,0,0,0,0,0.0 +356,POST,14,0,1935,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +357,POST,15,0,774,23,1702,82,6253,59,72.8,0,0,0,0,0,0.0 +358,GET,5,2,0,9,688,33,2117,24,67.5,4,424,5,360,1,-17.8 +359,GET,3,1,0,6,526,23,1577,17,66.6,3,352,3,216,0,-63.0 +360,POST,7,0,1242,12,849,44,3091,32,72.5,0,0,0,0,0,0.0 +361,GET,5,5,0,9,688,33,2165,24,68.2,7,640,11,1024,4,37.5 +362,POST,14,0,1266,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +363,GET,7,1,0,11,832,42,3061,31,72.8,3,352,3,216,0,-63.0 +364,GET,2,4,0,4,400,16,960,12,58.3,6,568,9,680,3,16.5 +365,GET,9,2,0,13,976,50,3509,37,72.2,4,424,5,360,1,-17.8 +366,POST,15,0,1065,23,1702,82,6255,59,72.8,0,0,0,0,0,0.0 +367,GET,13,4,0,19,1309,70,4569,51,71.4,6,568,9,680,3,16.5 +368,POST,17,0,1149,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +369,GET,14,4,0,21,1613,75,5022,54,67.9,6,568,9,680,3,16.5 +370,GET,10,0,0,14,1048,54,3698,40,71.7,0,0,0,0,0,0.0 +371,GET,2,2,0,4,400,16,928,12,56.9,4,424,5,360,1,-17.8 +372,POST,14,0,1271,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +373,POST,13,0,1649,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +374,GET,14,0,0,21,1613,75,4958,54,67.5,0,0,0,0,0,0.0 +375,POST,4,0,2008,7,561,27,1646,20,65.9,0,0,0,0,0,0.0 +376,GET,10,3,0,14,1048,54,3746,40,72.0,5,496,8,592,3,16.2 +377,POST,9,0,1136,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +378,GET,3,5,0,6,526,23,1641,17,67.9,7,640,11,1024,4,37.5 +379,POST,8,0,1121,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +380,POST,10,0,1605,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +381,POST,9,0,610,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +382,POST,11,0,1766,16,1137,60,3971,44,71.4,0,0,0,0,0,0.0 +383,POST,17,0,1631,25,1846,89,6660,64,72.3,0,0,0,0,0,0.0 +384,GET,8,5,0,12,904,46,3336,34,72.9,7,640,11,1024,4,37.5 +385,POST,10,0,1575,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +386,GET,2,2,0,4,400,16,928,12,56.9,4,424,5,360,1,-17.8 +387,GET,15,3,0,22,1685,79,6214,57,72.9,5,496,8,592,3,16.2 +388,GET,6,1,0,10,760,37,2324,27,67.3,3,352,3,216,0,-63.0 +389,GET,10,3,0,14,1048,54,3746,40,72.0,5,496,8,592,3,16.2 +390,GET,6,0,0,10,760,37,2308,27,67.1,0,0,0,0,0,0.0 +391,POST,5,0,942,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +392,GET,10,0,0,14,1048,54,3698,40,71.7,0,0,0,0,0,0.0 +393,GET,3,4,0,6,526,23,1625,17,67.6,6,568,9,680,3,16.5 +394,POST,6,0,372,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +395,POST,8,0,843,13,921,48,3312,35,72.2,0,0,0,0,0,0.0 +396,POST,16,0,971,24,1774,86,6474,62,72.6,0,0,0,0,0,0.0 +397,POST,13,0,1993,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +398,GET,10,1,0,14,1048,54,3714,40,71.8,3,352,3,216,0,-63.0 +399,GET,2,4,0,4,400,16,960,12,58.3,6,568,9,680,3,16.5 +400,GET,6,1,0,10,760,37,2322,27,67.3,3,352,3,216,0,-63.0 +401,GET,4,0,0,7,598,27,1800,20,66.8,0,0,0,0,0,0.0 +402,GET,9,0,0,13,976,50,3475,37,71.9,0,0,0,0,0,0.0 +403,POST,10,0,729,15,1065,56,3746,41,71.6,0,0,0,0,0,0.0 +404,GET,14,2,0,21,1613,75,4988,54,67.7,4,424,5,360,1,-17.8 +405,GET,9,1,0,13,976,50,3491,37,72.0,3,352,3,216,0,-63.0 +406,POST,8,0,80,13,921,48,3308,35,72.2,0,0,0,0,0,0.0 +407,GET,13,2,0,19,1309,70,4535,51,71.1,4,424,5,360,1,-17.8 +408,POST,13,0,167,18,1281,68,4427,50,71.1,0,0,0,0,0,0.0 +409,POST,16,0,321,24,1774,86,6472,62,72.6,0,0,0,0,0,0.0 +410,POST,9,0,125,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +411,GET,5,5,0,9,688,33,2165,24,68.2,7,640,11,1024,4,37.5 +412,POST,5,0,1533,9,687,33,2055,24,66.6,0,0,0,0,0,0.0 +413,POST,6,0,2020,10,759,37,2296,27,66.9,0,0,0,0,0,0.0 +414,GET,9,2,0,13,976,50,3509,37,72.2,4,424,5,360,1,-17.8 +415,POST,10,0,483,15,1065,56,3748,41,71.6,0,0,0,0,0,0.0 +416,POST,14,0,755,21,1610,75,4956,54,67.5,0,0,0,0,0,0.0 +417,POST,10,0,1476,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +418,POST,4,0,75,7,561,27,1642,20,65.8,0,0,0,0,0,0.0 +419,GET,5,0,0,9,688,33,2085,24,67.0,0,0,0,0,0,0.0 +420,POST,13,0,1834,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +421,POST,11,0,1535,16,1137,60,3971,44,71.4,0,0,0,0,0,0.0 +422,POST,4,0,219,7,561,27,1644,20,65.9,0,0,0,0,0,0.0 +423,POST,10,0,725,15,1065,56,3748,41,71.6,0,0,0,0,0,0.0 +424,POST,9,0,496,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +425,GET,5,4,0,9,688,33,2149,24,68.0,6,568,9,680,3,16.5 +426,GET,4,0,0,7,598,27,1802,20,66.8,0,0,0,0,0,0.0 +427,POST,8,0,1722,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +428,GET,3,1,0,6,526,23,1577,17,66.6,3,352,3,216,0,-63.0 +429,POST,5,0,477,9,687,33,2053,24,66.5,0,0,0,0,0,0.0 +430,POST,8,0,1216,13,921,48,3314,35,72.2,0,0,0,0,0,0.0 +431,GET,11,2,0,15,1120,58,3969,43,71.8,4,424,5,360,1,-17.8 +432,POST,13,0,1021,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +433,GET,3,3,0,6,526,23,1609,17,67.3,5,496,8,592,3,16.2 +434,POST,14,0,1202,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +435,POST,14,0,1201,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +436,GET,9,0,0,13,976,50,3477,37,71.9,0,0,0,0,0,0.0 +437,GET,5,2,0,9,688,33,2117,24,67.5,4,424,5,360,1,-17.8 +438,GET,14,3,0,21,1613,75,5006,54,67.8,5,496,8,592,3,16.2 +439,POST,11,0,500,16,1137,60,3969,44,71.4,0,0,0,0,0,0.0 +440,GET,8,5,0,12,904,46,3336,34,72.9,7,640,11,1024,4,37.5 +441,GET,10,5,0,14,1048,54,3778,40,72.3,7,640,11,1024,4,37.5 +442,GET,2,0,0,4,400,16,896,12,55.4,0,0,0,0,0,0.0 +443,GET,4,2,0,7,598,27,1834,20,67.4,4,424,5,360,1,-17.8 +444,GET,8,0,0,12,904,46,3256,34,72.2,0,0,0,0,0,0.0 +445,POST,6,0,180,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +446,GET,13,1,0,19,1309,70,4521,51,71.0,3,352,3,216,0,-63.0 +447,GET,14,5,0,21,1613,75,5038,54,68.0,7,640,11,1024,4,37.5 +448,GET,2,3,0,4,400,16,944,12,57.6,5,496,8,592,3,16.2 +449,GET,7,4,0,11,832,42,3109,31,73.2,6,568,9,680,3,16.5 +450,POST,17,0,229,25,1846,89,6658,64,72.3,0,0,0,0,0,0.0 +451,POST,9,0,1180,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +452,POST,16,0,1773,24,1774,86,6476,62,72.6,0,0,0,0,0,0.0 +453,GET,13,5,0,19,1309,70,4585,51,71.5,7,640,11,1024,4,37.5 +454,GET,8,1,0,12,904,46,3272,34,72.4,3,352,3,216,0,-63.0 +455,POST,13,0,1681,18,1281,68,4431,50,71.1,0,0,0,0,0,0.0 +456,POST,14,0,1140,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +457,POST,12,0,976,17,1209,64,4190,47,71.1,0,0,0,0,0,0.0 +458,GET,13,4,0,19,1309,70,4569,51,71.4,6,568,9,680,3,16.5 +459,GET,4,5,0,7,598,27,1882,20,68.2,7,640,11,1024,4,37.5 +460,GET,11,2,0,15,1120,58,3969,43,71.8,4,424,5,360,1,-17.8 +461,GET,9,4,0,13,976,50,3541,37,72.4,6,568,9,680,3,16.5 +462,GET,9,0,0,13,976,50,3477,37,71.9,0,0,0,0,0,0.0 +463,POST,12,0,1573,17,1209,64,4192,47,71.2,0,0,0,0,0,0.0 +464,GET,3,3,0,6,526,23,1609,17,67.3,5,496,8,592,3,16.2 +465,POST,6,0,1909,10,759,37,2296,27,66.9,0,0,0,0,0,0.0 +466,GET,6,3,0,10,760,37,2356,27,67.7,5,496,8,592,3,16.2 +467,POST,4,0,756,7,561,27,1644,20,65.9,0,0,0,0,0,0.0 +468,GET,8,0,0,12,904,46,3256,34,72.2,0,0,0,0,0,0.0 +469,POST,4,0,1124,7,561,27,1646,20,65.9,0,0,0,0,0,0.0 +470,POST,6,0,660,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +471,POST,15,0,180,23,1702,82,6253,59,72.8,0,0,0,0,0,0.0 +472,GET,3,4,0,6,526,23,1625,17,67.6,6,568,9,680,3,16.5 +473,GET,12,0,0,17,1217,64,4232,47,71.2,0,0,0,0,0,0.0 +474,POST,10,0,966,15,1065,56,3748,41,71.6,0,0,0,0,0,0.0 +475,POST,9,0,1627,14,993,52,3539,38,71.9,0,0,0,0,0,0.0 +476,GET,3,5,0,6,526,23,1641,17,67.9,7,640,11,1024,4,37.5 +477,POST,15,0,1528,23,1702,82,6255,59,72.8,0,0,0,0,0,0.0 +478,POST,9,0,254,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +479,POST,14,0,2030,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +480,POST,6,0,371,10,759,37,2294,27,66.9,0,0,0,0,0,0.0 +481,GET,2,5,0,4,400,16,976,12,59.0,7,640,11,1024,4,37.5 +482,POST,14,0,1177,21,1610,75,4958,54,67.5,0,0,0,0,0,0.0 +483,GET,13,4,0,19,1309,70,4569,51,71.4,6,568,9,680,3,16.5 +484,GET,13,4,0,19,1309,70,4569,51,71.4,6,568,9,680,3,16.5 +485,POST,6,0,1638,10,759,37,2296,27,66.9,0,0,0,0,0,0.0 +486,GET,13,0,0,19,1309,70,4505,51,70.9,0,0,0,0,0,0.0 +487,GET,13,1,0,19,1309,70,4521,51,71.0,3,352,3,216,0,-63.0 +488,POST,12,0,1071,17,1209,64,4192,47,71.2,0,0,0,0,0,0.0 +489,POST,9,0,647,14,993,52,3537,38,71.9,0,0,0,0,0,0.0 +490,POST,12,0,804,17,1209,64,4190,47,71.1,0,0,0,0,0,0.0 +491,POST,15,0,926,23,1702,82,6253,59,72.8,0,0,0,0,0,0.0 +492,GET,11,2,0,15,1120,58,3969,43,71.8,4,424,5,360,1,-17.8 +493,POST,10,0,1278,15,1065,56,3750,41,71.6,0,0,0,0,0,0.0 +494,GET,9,4,0,13,976,50,3541,37,72.4,6,568,9,680,3,16.5 +495,GET,9,3,0,13,976,50,3525,37,72.3,5,496,8,592,3,16.2 +496,GET,6,5,0,10,760,37,2388,27,68.2,7,640,11,1024,4,37.5 +497,GET,7,3,0,11,832,42,3093,31,73.1,5,496,8,592,3,16.2 +498,POST,4,0,1857,7,561,27,1646,20,65.9,0,0,0,0,0,0.0 +499,GET,10,3,0,14,1048,54,3746,40,72.0,5,496,8,592,3,16.2 diff --git a/test/performance/http-parser/results-performance.csv b/test/performance/http-parser/results-performance.csv new file mode 100644 index 0000000..3851a31 --- /dev/null +++ b/test/performance/http-parser/results-performance.csv @@ -0,0 +1,501 @@ +request_idx,method,header_count,url_param_count,payload_size,new_header_avg_ns,new_header_min_ns,new_header_max_ns,legacy_header_avg_ns,legacy_header_min_ns,legacy_header_max_ns,header_speedup_x,new_getparam_avg_ns,new_getparam_min_ns,new_getparam_max_ns,legacy_getparam_avg_ns,legacy_getparam_min_ns,legacy_getparam_max_ns,getparam_speedup_x +0,GET,13,5,0,976,891,27631,2186,2103,21540,2.24,295,290,612,420,410,881,1.42 +1,GET,12,4,0,850,821,2325,2014,1943,22091,2.37,296,240,2815,615,320,27892,2.08 +2,POST,12,0,319,867,841,2585,1919,1834,22472,2.21,31,29,51,30,29,91,0.97 +3,GET,4,0,0,364,290,18094,743,731,1352,2.04,31,29,41,30,29,41,0.97 +4,GET,8,5,0,584,570,1042,1374,1333,3196,2.35,305,290,2164,472,411,14376,1.55 +5,GET,10,0,0,709,691,1463,1612,1552,12874,2.27,31,29,41,30,29,41,0.97 +6,POST,13,0,42,970,901,18826,2071,1983,22001,2.14,31,29,50,31,29,101,1.00 +7,GET,15,4,0,1311,1162,24857,2637,2424,14507,2.01,250,240,991,336,330,931,1.34 +8,POST,17,0,435,1525,1302,22192,3011,2665,27030,1.97,31,29,70,30,29,80,0.97 +9,GET,4,5,0,310,290,1022,809,771,15068,2.61,295,290,771,423,410,1182,1.43 +10,GET,10,1,0,729,711,1523,1775,1592,14317,2.43,107,100,651,111,100,391,1.04 +11,POST,11,0,14,790,771,1593,1822,1733,21631,2.31,31,29,51,30,29,70,0.97 +12,GET,2,1,0,190,180,591,464,430,12103,2.44,106,100,310,111,100,250,1.05 +13,POST,12,0,819,860,841,1603,1915,1844,21000,2.23,31,29,71,30,29,41,0.97 +14,GET,2,1,0,210,180,10409,438,430,692,2.09,104,100,170,110,100,190,1.06 +15,POST,9,0,476,651,631,1052,1522,1442,25047,2.34,31,29,90,30,29,50,0.97 +16,GET,3,4,0,250,240,611,673,641,11963,2.69,250,240,651,330,320,852,1.32 +17,POST,6,0,783,491,430,17433,1019,1001,2445,2.08,31,29,101,30,29,40,0.97 +18,POST,17,0,1213,1401,1302,11551,2730,2674,11341,1.95,31,29,41,64,29,15810,2.06 +19,GET,2,5,0,187,180,521,467,450,902,2.50,298,290,611,416,410,921,1.40 +20,POST,13,0,349,940,901,2094,2051,1994,11933,2.18,31,29,50,30,29,41,0.97 +21,GET,2,0,0,188,180,320,486,420,24596,2.59,31,29,41,30,29,40,0.97 +22,POST,17,0,1978,1392,1302,2625,2808,2685,22162,2.02,31,29,80,31,29,41,1.00 +23,POST,15,0,789,1235,1192,10730,2488,2434,11612,2.01,31,29,41,30,29,41,0.97 +24,GET,2,0,0,191,180,281,478,420,17022,2.50,31,29,41,30,29,41,0.97 +25,GET,11,1,0,775,751,1403,1801,1743,15049,2.32,112,100,2344,111,100,310,0.99 +26,GET,11,0,0,794,751,11772,1825,1703,21129,2.30,31,29,101,30,29,51,0.97 +27,POST,10,0,1707,722,701,1323,1637,1582,20068,2.27,31,29,41,31,29,100,1.00 +28,GET,4,5,0,308,291,642,821,771,14337,2.67,294,290,701,416,410,1032,1.41 +29,GET,5,1,0,403,370,10310,914,901,1352,2.27,107,100,200,111,100,221,1.04 +30,POST,14,0,638,1129,1082,10279,2308,2234,18915,2.04,31,29,41,30,29,41,0.97 +31,GET,9,1,0,718,631,15178,1483,1462,2545,2.07,126,100,9528,112,100,290,0.89 +32,POST,11,0,378,779,761,1202,1788,1723,18865,2.30,35,29,2265,30,29,100,0.86 +33,GET,15,5,0,1224,1152,14187,2519,2444,15659,2.06,299,290,601,437,410,10360,1.46 +34,POST,10,0,1925,722,701,1072,1625,1583,10850,2.25,31,29,41,30,29,41,0.97 +35,GET,14,5,0,1170,1092,18295,2364,2304,16370,2.02,298,290,581,440,410,10670,1.48 +36,POST,14,0,1888,1113,1082,2004,2315,2224,20158,2.08,33,29,601,30,29,41,0.91 +37,GET,3,3,0,253,250,601,645,631,1253,2.55,201,190,411,265,260,561,1.32 +38,GET,9,0,0,678,621,19076,1484,1422,11422,2.19,31,29,80,30,29,40,0.97 +39,POST,8,0,1730,593,571,1172,1341,1302,1923,2.26,31,29,120,30,29,41,0.97 +40,GET,12,1,0,841,821,1473,2289,1963,21911,2.72,172,150,962,180,150,621,1.05 +41,POST,15,0,1202,1872,1553,29114,3948,2414,29716,2.11,34,29,110,33,29,70,0.97 +42,GET,15,1,0,1803,1163,20618,4828,4218,45855,2.68,181,150,862,185,150,601,1.02 +43,POST,11,0,565,1224,1042,23704,3513,2865,28654,2.87,36,29,90,35,29,80,0.97 +44,GET,6,4,0,760,621,19106,2097,1873,28253,2.76,446,400,1282,623,521,1372,1.40 +45,GET,3,0,0,429,350,24827,1167,1072,2014,2.72,36,29,111,35,29,60,0.97 +46,POST,9,0,1582,1016,902,18685,1950,1442,20127,1.92,31,29,41,30,29,50,0.97 +47,GET,4,1,0,309,300,791,955,741,17173,3.09,106,100,651,112,100,510,1.06 +48,GET,2,4,0,194,180,3055,452,440,761,2.33,258,240,841,331,320,882,1.28 +49,GET,11,4,0,779,761,1573,1819,1744,23063,2.34,246,240,430,364,320,16591,1.48 +50,POST,15,0,1580,1219,1182,3116,2557,2424,21410,2.10,31,29,41,30,29,90,0.97 +51,POST,5,0,1897,561,380,3276,1865,861,22672,3.32,36,29,101,36,29,91,1.00 +52,GET,11,0,0,1164,761,22433,3180,1703,26520,2.73,36,29,90,33,29,71,0.92 +53,POST,16,0,1741,1968,1813,23975,4101,2575,28042,2.08,31,29,70,30,29,60,0.97 +54,POST,10,0,678,776,701,22442,1646,1572,28363,2.12,33,29,100,34,29,601,1.03 +55,GET,2,2,0,192,180,2074,514,430,3406,2.68,178,150,2905,196,170,882,1.10 +56,GET,11,1,0,863,761,4037,1822,1733,25728,2.11,106,100,471,111,100,411,1.05 +57,POST,14,0,1211,1173,1102,22893,2258,2224,4198,1.92,31,29,50,30,29,41,0.97 +58,POST,7,0,1817,560,510,17443,1194,1172,2004,2.13,31,29,90,30,29,40,0.97 +59,POST,10,0,784,770,701,19356,1636,1572,19647,2.12,31,29,41,30,29,41,0.97 +60,GET,15,4,0,1190,1152,2355,2503,2434,13004,2.10,249,240,772,330,320,872,1.33 +61,POST,14,0,1478,1130,1082,12724,2270,2224,11302,2.01,31,29,41,31,29,80,1.00 +62,POST,7,0,1579,528,510,832,1212,1172,13605,2.30,31,29,41,30,29,41,0.97 +63,GET,8,0,0,596,561,9839,1318,1302,2093,2.21,31,29,41,30,29,41,0.97 +64,POST,13,0,876,941,901,10079,2053,2003,11090,2.18,31,29,41,30,29,41,0.97 +65,GET,2,2,0,191,180,360,463,440,9007,2.42,155,150,582,179,170,421,1.15 +66,GET,4,0,0,306,290,861,753,741,3647,2.46,31,29,41,30,29,90,0.97 +67,POST,12,0,974,866,841,1322,1892,1843,10319,2.18,31,29,130,30,29,41,0.97 +68,GET,9,3,0,638,621,971,1510,1462,10079,2.37,200,190,421,306,260,20068,1.53 +69,POST,16,0,285,1275,1242,2465,2742,2554,37270,2.15,33,29,180,30,29,70,0.91 +70,GET,10,2,0,744,711,1573,1648,1603,12584,2.22,155,150,461,206,170,14257,1.33 +71,POST,14,0,416,1121,1072,8957,2797,2214,33132,2.50,31,29,41,30,29,50,0.97 +72,GET,15,0,0,1220,1162,11402,2466,2374,13426,2.02,31,29,41,30,29,41,0.97 +73,POST,8,0,1423,592,570,1122,1375,1312,10610,2.32,31,29,41,30,29,41,0.97 +74,GET,14,5,0,1137,1091,10340,2355,2294,11261,2.07,294,290,682,444,420,9298,1.51 +75,POST,15,0,605,1237,1182,2305,2530,2434,14046,2.05,31,29,41,30,29,50,0.97 +76,POST,5,0,1785,390,380,711,926,871,4669,2.37,31,29,41,31,29,90,1.00 +77,GET,13,1,0,916,892,1744,2148,2064,11231,2.34,106,100,300,111,100,270,1.05 +78,GET,7,5,0,524,491,9387,1222,1202,1793,2.33,313,290,9538,425,420,802,1.36 +79,POST,11,0,664,790,761,1273,1760,1713,10841,2.23,31,29,41,30,29,40,0.97 +80,POST,5,0,1836,409,380,9177,880,871,1343,2.15,31,29,41,31,29,100,1.00 +81,GET,6,5,0,462,430,9197,1069,1051,1843,2.31,292,290,431,510,420,42860,1.75 +82,GET,5,1,0,387,370,711,921,901,1583,2.38,103,100,200,131,100,10149,1.27 +83,POST,9,0,1,653,631,1022,1474,1423,17121,2.26,31,29,41,30,29,41,0.97 +84,POST,8,0,1763,590,570,912,1425,1312,12293,2.42,31,29,41,30,29,41,0.97 +85,GET,2,0,0,187,180,381,459,430,671,2.45,31,29,41,30,29,90,0.97 +86,POST,11,0,855,781,761,1502,1829,1723,40856,2.34,31,29,41,30,29,40,0.97 +87,GET,5,4,0,381,370,812,1646,921,12804,4.32,246,240,932,441,320,16110,1.79 +88,GET,5,2,0,383,370,1302,1056,901,4919,2.76,188,150,2645,204,170,3065,1.09 +89,GET,15,1,0,1377,1162,16831,2626,2454,21731,1.91,106,100,340,111,100,331,1.05 +90,GET,5,3,0,383,370,842,963,921,10660,2.51,198,190,411,267,260,581,1.35 +91,POST,13,0,827,971,901,11081,2053,1994,10689,2.11,31,29,50,30,29,40,0.97 +92,GET,2,5,0,187,180,400,462,451,721,2.47,312,290,9097,426,420,862,1.37 +93,GET,15,1,0,1208,1152,9879,2514,2454,11772,2.08,104,100,210,110,100,211,1.06 +94,GET,11,2,0,786,741,9598,1755,1703,11692,2.23,153,150,291,180,170,331,1.18 +95,POST,8,0,303,591,570,951,1360,1312,10220,2.30,31,29,41,30,29,41,0.97 +96,GET,15,0,0,1229,1182,9899,2447,2384,11621,1.99,31,29,41,30,29,40,0.97 +97,GET,10,5,0,742,711,9378,1629,1612,2545,2.20,326,280,8757,629,420,3868,1.93 +98,POST,9,0,105,656,631,1773,1492,1433,13625,2.27,31,29,50,30,29,41,0.97 +99,GET,5,2,0,406,380,9438,920,901,1443,2.27,154,150,461,177,170,371,1.15 +100,POST,12,0,490,884,841,10199,1876,1833,11020,2.12,31,29,41,30,29,41,0.97 +101,POST,6,0,1087,449,430,721,1028,1001,10009,2.29,31,29,70,30,29,41,0.97 +102,GET,8,5,0,578,561,942,1376,1342,10019,2.38,299,290,541,421,410,791,1.41 +103,POST,7,0,1214,525,510,852,1187,1172,1744,2.26,31,29,41,30,29,90,0.97 +104,POST,5,0,1560,408,380,9398,1032,861,4668,2.53,33,29,250,32,29,180,0.97 +105,GET,5,1,0,463,370,11682,918,901,1693,1.98,146,100,2815,110,100,401,0.75 +106,POST,15,0,753,1488,1182,23975,3486,2445,25487,2.34,31,29,71,30,29,51,0.97 +107,GET,10,5,0,769,701,23163,1653,1612,11461,2.15,296,290,851,423,410,1232,1.43 +108,POST,9,0,1097,712,631,3347,1479,1432,12633,2.08,31,29,41,31,29,41,1.00 +109,POST,5,0,1635,389,380,602,874,861,1362,2.25,31,29,80,30,29,40,0.97 +110,POST,6,0,657,448,440,631,1030,1001,9838,2.30,31,29,41,30,29,41,0.97 +111,POST,6,0,1425,447,430,531,1007,992,1282,2.25,31,29,90,30,29,41,0.97 +112,GET,14,3,0,1226,1102,44644,2391,2284,13224,1.95,200,190,611,266,260,751,1.33 +113,GET,11,1,0,798,751,11952,1778,1733,11902,2.23,104,100,221,109,100,260,1.05 +114,GET,11,3,0,776,751,1183,1779,1743,11862,2.29,199,190,361,265,260,530,1.33 +115,POST,7,0,714,530,510,872,1206,1172,10159,2.28,31,29,41,31,29,90,1.00 +116,POST,5,0,357,392,380,631,911,871,9848,2.32,31,29,41,30,29,41,0.97 +117,POST,13,0,814,923,892,1552,2049,1993,10830,2.22,31,29,41,30,29,81,0.97 +118,GET,9,5,0,659,621,9688,1519,1482,10019,2.31,304,300,541,503,410,3426,1.65 +119,POST,5,0,1384,394,380,922,908,871,12814,2.30,31,29,80,30,29,41,0.97 +120,GET,12,0,0,840,811,1653,1951,1873,11081,2.32,31,29,60,30,29,41,0.97 +121,GET,14,3,0,1123,1092,2364,2362,2284,11712,2.10,198,190,501,272,260,561,1.37 +122,POST,13,0,528,928,901,1603,2046,1994,11041,2.20,31,29,41,31,29,41,1.00 +123,GET,11,1,0,771,751,1242,1768,1733,10880,2.29,102,100,331,109,100,221,1.07 +124,POST,17,0,1137,1400,1313,2445,2765,2705,11711,1.98,31,29,110,30,29,41,0.97 +125,POST,11,0,534,782,761,1262,1760,1713,10660,2.25,31,29,41,34,29,2114,1.10 +126,GET,15,0,0,1201,1152,2264,2450,2374,14207,2.04,31,29,41,30,29,41,0.97 +127,POST,16,0,1143,1290,1232,10179,2648,2584,11461,2.05,31,29,41,30,29,41,0.97 +128,POST,16,0,1297,1274,1242,1883,2623,2564,11672,2.06,31,29,41,30,29,40,0.97 +129,GET,6,1,0,443,430,721,1220,1031,70011,2.75,104,100,391,110,100,321,1.06 +130,GET,11,4,0,772,751,1563,1804,1753,14066,2.34,249,240,461,351,321,9267,1.41 +131,POST,16,0,1754,1281,1242,4188,2649,2574,12103,2.07,31,29,41,30,29,41,0.97 +132,POST,9,0,1597,667,641,1252,1471,1442,10310,2.21,32,29,160,30,29,41,0.94 +133,POST,12,0,1743,885,841,9909,1900,1843,10219,2.15,31,29,41,30,29,111,0.97 +134,GET,15,0,0,1207,1162,9819,2423,2384,4078,2.01,31,29,41,30,29,41,0.97 +135,POST,16,0,1370,1290,1242,10149,2645,2584,11752,2.05,31,29,41,30,29,91,0.97 +136,POST,12,0,18,891,841,9368,1891,1843,10750,2.12,31,29,41,30,29,41,0.97 +137,GET,3,5,0,251,240,501,653,641,932,2.60,316,290,9107,421,410,811,1.33 +138,POST,17,0,10,1412,1312,11071,2753,2695,11381,1.95,31,29,80,30,29,41,0.97 +139,GET,4,1,0,327,300,8807,761,751,1162,2.33,105,100,220,110,100,211,1.05 +140,POST,10,0,1417,755,712,9608,1609,1583,2444,2.13,31,29,90,48,29,8767,1.55 +141,GET,11,5,0,861,781,1713,2201,1733,24156,2.56,294,290,852,447,411,11752,1.52 +142,GET,4,4,0,316,301,922,782,761,1182,2.47,248,240,420,332,320,621,1.34 +143,GET,5,2,0,381,370,652,927,901,3586,2.43,172,150,9308,177,170,381,1.03 +144,GET,4,4,0,311,300,441,767,761,1032,2.47,274,240,13295,330,320,531,1.20 +145,GET,11,4,0,788,771,1413,1802,1753,10600,2.29,252,240,511,379,330,17583,1.50 +146,POST,14,0,1347,1109,1082,2415,2298,2224,12874,2.07,47,29,8455,30,29,41,0.64 +147,GET,9,3,0,641,621,1212,1511,1472,9959,2.36,198,190,471,270,260,571,1.36 +148,GET,9,2,0,639,621,1092,1508,1472,10489,2.36,154,150,371,193,170,8806,1.25 +149,POST,7,0,513,529,510,901,1210,1172,9678,2.29,31,29,41,30,29,41,0.97 +150,GET,10,5,0,709,691,1333,1653,1612,10609,2.33,295,290,480,420,410,831,1.42 +151,POST,9,0,997,656,641,1022,1477,1442,11270,2.25,31,29,80,30,29,41,0.97 +152,POST,16,0,1293,1274,1232,2455,2644,2565,11702,2.08,31,29,321,30,29,91,0.97 +153,GET,13,2,0,934,891,9798,2139,2083,10660,2.29,155,150,331,177,170,430,1.14 +154,POST,13,0,1182,926,901,1553,2107,1993,19135,2.28,31,29,41,30,29,100,0.97 +155,POST,10,0,1770,718,691,1343,1619,1573,11131,2.25,31,29,70,35,29,2274,1.13 +156,GET,5,4,0,382,370,702,952,921,9758,2.49,251,240,611,330,320,672,1.31 +157,GET,5,3,0,385,370,581,946,921,10139,2.46,201,190,301,265,260,471,1.32 +158,GET,12,3,0,864,811,10369,1953,1933,2976,2.26,200,190,311,268,260,370,1.34 +159,GET,4,5,0,310,300,611,823,781,9979,2.65,298,290,411,421,410,652,1.41 +160,POST,10,0,1954,754,711,9658,1615,1582,10409,2.14,31,29,41,30,29,40,0.97 +161,GET,14,5,0,1167,1131,2084,2365,2294,11231,2.03,293,290,421,419,410,661,1.43 +162,GET,12,0,0,868,821,11411,1908,1863,10209,2.20,31,29,41,30,29,41,0.97 +163,POST,16,0,677,1295,1252,10329,2624,2564,11422,2.03,31,29,89,30,29,41,0.97 +164,GET,9,5,0,652,631,1021,1520,1483,10199,2.33,294,280,631,442,410,9117,1.50 +165,POST,17,0,2008,1413,1302,10088,2774,2685,22121,1.96,31,29,41,30,29,41,0.97 +166,POST,5,0,603,395,380,792,906,871,11011,2.29,31,29,41,30,29,41,0.97 +167,GET,7,1,0,510,490,1012,1250,1212,10179,2.45,103,100,261,110,100,260,1.07 +168,POST,7,0,649,524,510,751,1189,1172,3236,2.27,31,29,150,31,29,41,1.00 +169,GET,4,2,0,308,300,721,774,751,1032,2.51,156,150,311,177,170,350,1.13 +170,POST,9,0,1918,666,641,1302,1473,1432,10660,2.21,32,29,89,30,29,41,0.94 +171,POST,13,0,1905,945,901,9869,2071,1993,11452,2.19,31,29,100,30,29,41,0.97 +172,POST,4,0,199,312,300,531,773,721,9858,2.48,31,29,121,30,29,41,0.97 +173,GET,10,4,0,718,701,1132,1644,1603,10319,2.29,249,240,451,351,320,9238,1.41 +174,POST,9,0,287,659,641,1142,1448,1432,2184,2.20,31,29,70,30,29,41,0.97 +175,GET,9,1,0,640,621,1042,1493,1452,9939,2.33,103,100,200,109,100,221,1.06 +176,POST,8,0,1517,610,570,9288,1340,1312,4007,2.20,31,29,110,30,29,41,0.97 +177,POST,13,0,279,938,892,9708,2062,2003,14768,2.20,31,29,41,30,29,41,0.97 +178,POST,13,0,736,945,901,10209,2050,2003,10771,2.17,31,29,41,30,29,41,0.97 +179,POST,8,0,607,588,571,981,1359,1312,10299,2.31,31,29,41,30,29,100,0.97 +180,POST,9,0,1659,651,631,882,1477,1442,11020,2.27,31,29,41,30,29,70,0.97 +181,GET,14,3,0,1139,1092,10209,2347,2284,10640,2.06,198,190,441,283,260,8877,1.43 +182,POST,5,0,1047,394,380,641,880,871,1313,2.23,31,29,41,30,29,80,0.97 +183,GET,9,3,0,645,631,1112,1497,1462,3727,2.32,201,190,331,268,260,441,1.33 +184,POST,6,0,1331,447,430,692,1031,1001,9909,2.31,31,29,40,30,29,41,0.97 +185,GET,11,2,0,781,761,1352,1775,1733,10449,2.27,153,150,291,178,170,360,1.16 +186,POST,4,0,1823,314,300,661,745,711,1073,2.37,31,29,41,30,29,41,0.97 +187,POST,8,0,56,622,570,13936,1333,1312,2084,2.14,31,29,140,30,29,41,0.97 +188,GET,10,0,0,856,691,9889,1786,1552,18344,2.09,31,29,50,30,29,50,0.97 +189,GET,10,4,0,711,691,1383,1639,1593,12814,2.31,269,240,9097,329,320,841,1.22 +190,GET,6,2,0,446,430,781,1095,1021,19767,2.46,153,150,351,176,170,431,1.15 +191,GET,9,5,0,642,621,3226,1531,1482,11411,2.38,292,290,461,440,420,8967,1.51 +192,GET,13,3,0,916,892,1573,2147,2094,11271,2.34,199,190,401,272,260,451,1.37 +193,POST,4,0,512,317,310,521,748,711,1243,2.36,31,29,41,31,29,90,1.00 +194,GET,2,4,0,191,180,451,458,450,661,2.40,247,240,381,331,330,571,1.34 +195,GET,7,3,0,507,500,791,1232,1192,9768,2.43,202,190,381,269,260,431,1.33 +196,GET,6,3,0,466,440,9558,1082,1071,1463,2.32,204,190,381,274,260,551,1.34 +197,POST,14,0,556,1113,1091,2234,2292,2234,11101,2.06,31,29,41,30,29,41,0.97 +198,GET,15,3,0,1200,1152,3456,2467,2384,11261,2.06,198,190,321,268,260,471,1.35 +199,GET,3,5,0,251,240,481,650,641,1002,2.59,311,290,9347,425,420,751,1.37 +200,GET,4,3,0,309,291,530,777,771,1172,2.51,216,190,9147,269,260,421,1.25 +201,GET,9,4,0,653,631,1163,1521,1473,10610,2.33,246,240,371,331,320,481,1.35 +202,POST,5,0,1487,409,380,9578,877,871,1412,2.14,31,29,41,30,29,100,0.97 +203,GET,15,5,0,1207,1153,9838,2510,2445,11331,2.08,294,280,581,438,410,9106,1.49 +204,POST,14,0,661,1111,1091,1843,2298,2233,11491,2.07,31,29,140,30,29,80,0.97 +205,GET,13,2,0,917,891,1553,2123,2083,3377,2.32,171,150,8857,176,170,411,1.03 +206,GET,8,2,0,580,570,1192,1368,1332,10038,2.36,154,150,241,176,170,241,1.14 +207,POST,5,0,514,389,380,592,902,871,10289,2.32,31,29,41,30,29,41,0.97 +208,GET,4,5,0,309,300,551,783,771,1062,2.53,313,290,9407,423,410,732,1.35 +209,GET,13,2,0,913,882,1583,2145,2083,11361,2.35,153,150,260,176,170,280,1.15 +210,POST,13,0,837,923,901,1543,2076,2004,11121,2.25,31,29,41,30,29,41,0.97 +211,GET,4,5,0,308,290,551,795,781,1072,2.58,300,290,611,439,410,9457,1.46 +212,GET,8,1,0,580,561,1001,1384,1332,9989,2.39,103,100,431,110,100,221,1.07 +213,GET,9,0,0,641,621,922,1486,1422,17873,2.32,31,29,90,30,29,41,0.97 +214,POST,6,0,1352,469,430,10920,1016,1001,1462,2.17,31,29,41,30,29,41,0.97 +215,POST,7,0,1307,544,501,9658,1189,1172,1744,2.19,31,29,130,31,29,90,1.00 +216,POST,11,0,1511,805,761,9648,1751,1713,10740,2.18,31,29,130,31,29,41,1.00 +217,POST,11,0,892,783,751,1082,1755,1713,10299,2.24,31,29,41,30,29,41,0.97 +218,POST,14,0,859,1124,1082,10179,2308,2244,11071,2.05,31,29,70,30,29,41,0.97 +219,GET,5,3,0,403,370,9417,953,941,1453,2.36,199,190,831,269,260,611,1.35 +220,GET,4,4,0,308,300,450,769,761,1122,2.50,246,240,361,337,330,541,1.37 +221,GET,2,2,0,185,180,341,442,430,711,2.39,153,150,260,178,170,351,1.16 +222,GET,3,0,0,247,240,400,674,641,9748,2.73,31,29,130,30,29,41,0.97 +223,GET,2,1,0,192,180,430,447,430,611,2.33,104,100,210,109,100,210,1.05 +224,POST,17,0,1441,1393,1292,10229,2756,2695,11852,1.98,31,29,80,30,29,80,0.97 +225,GET,8,0,0,578,561,862,1401,1302,11051,2.42,31,29,41,30,29,41,0.97 +226,GET,12,2,0,839,821,1372,1993,1934,12103,2.38,155,150,411,195,170,8636,1.26 +227,POST,10,0,709,739,711,1152,1624,1572,10339,2.20,31,29,41,30,29,41,0.97 +228,GET,8,2,0,587,561,952,1380,1332,10209,2.35,155,150,330,176,170,320,1.14 +229,POST,9,0,98,677,641,9307,1454,1432,2134,2.15,31,29,41,30,29,80,0.97 +230,POST,17,0,1301,1385,1302,2915,2766,2705,11371,2.00,31,29,41,30,29,81,0.97 +231,POST,4,0,534,321,310,451,770,741,9347,2.40,31,29,41,30,29,41,0.97 +232,GET,2,3,0,188,180,361,447,440,1433,2.38,201,200,551,264,260,511,1.31 +233,POST,11,0,1026,807,761,14628,1737,1713,2725,2.15,31,29,41,30,29,70,0.97 +234,POST,11,0,1349,778,751,1223,1754,1713,10219,2.25,31,29,69,30,29,41,0.97 +235,POST,6,0,1261,464,430,9327,1081,1001,4077,2.33,31,29,41,30,29,41,0.97 +236,GET,15,3,0,1244,1152,11532,2517,2434,12463,2.02,198,190,501,265,260,601,1.34 +237,POST,4,0,1776,311,300,501,799,731,3987,2.57,59,29,13575,31,29,51,0.53 +238,POST,12,0,1926,891,841,3928,1900,1853,13745,2.13,31,29,41,30,29,90,0.97 +239,POST,12,0,1387,889,841,9779,1914,1863,10710,2.15,31,29,91,30,29,41,0.97 +240,GET,10,3,0,719,691,1102,1644,1592,10921,2.29,199,190,552,265,260,681,1.33 +241,GET,8,4,0,584,570,1062,1359,1332,4708,2.33,248,240,410,331,320,581,1.33 +242,POST,15,0,1929,1291,1192,11111,2508,2434,11662,1.94,31,29,41,30,29,100,0.97 +243,POST,9,0,1681,671,631,9669,1490,1462,2304,2.22,31,29,41,30,29,41,0.97 +244,POST,13,0,1855,926,901,1572,2046,1993,10660,2.21,31,29,41,30,29,81,0.97 +245,GET,4,1,0,311,300,661,789,751,9998,2.54,103,100,280,109,100,310,1.06 +246,GET,5,0,0,381,370,732,960,881,19998,2.52,31,29,101,30,29,41,0.97 +247,GET,2,0,0,188,180,421,434,420,622,2.31,31,29,100,30,29,41,0.97 +248,GET,10,4,0,739,691,11662,1654,1603,10319,2.24,247,240,490,329,320,671,1.33 +249,GET,2,3,0,194,180,2735,444,440,722,2.29,215,190,8886,265,260,491,1.23 +250,GET,7,5,0,509,490,962,1786,1212,23274,3.51,475,290,1102,472,410,21400,0.99 +251,POST,4,0,697,317,300,972,752,731,1633,2.37,31,29,41,31,29,41,1.00 +252,POST,7,0,577,545,510,10469,1190,1172,1844,2.18,31,29,41,31,29,41,1.00 +253,GET,3,4,0,263,240,9247,642,631,1031,2.44,247,240,501,329,320,571,1.33 +254,POST,8,0,1288,625,590,11601,1367,1332,2114,2.19,31,29,41,31,29,41,1.00 +255,POST,16,0,80,1280,1242,2775,2670,2585,11181,2.09,31,29,110,30,29,100,0.97 +256,POST,9,0,1646,665,641,1152,1473,1442,10019,2.22,31,29,100,30,29,41,0.97 +257,POST,7,0,1122,533,510,3457,1203,1171,10289,2.26,31,29,41,30,29,90,0.97 +258,GET,7,4,0,504,490,751,1247,1212,9819,2.47,246,240,481,331,320,572,1.35 +259,POST,15,0,1180,1211,1182,2335,2503,2424,11171,2.07,31,29,41,30,29,41,0.97 +260,POST,14,0,845,1109,1082,1804,2345,2234,11051,2.11,31,29,41,30,29,100,0.97 +261,GET,7,1,0,508,490,912,1250,1212,10229,2.46,104,100,241,110,100,260,1.06 +262,POST,12,0,698,875,851,1523,1884,1843,10810,2.15,31,29,41,30,29,90,0.97 +263,POST,17,0,1151,1381,1302,3687,2909,2694,13886,2.11,31,29,130,30,29,41,0.97 +264,POST,7,0,879,522,510,1232,1337,1172,23154,2.56,35,29,611,32,29,70,0.91 +265,POST,14,0,1516,1382,1082,21971,2379,2204,12684,1.72,34,29,211,34,29,70,1.00 +266,POST,7,0,211,732,510,37761,1259,1162,5561,1.72,39,29,2395,31,29,51,0.79 +267,GET,14,3,0,1287,1092,4428,2558,2264,23573,1.99,200,190,901,265,260,871,1.32 +268,POST,10,0,1693,716,701,1513,1620,1572,10980,2.26,31,29,41,30,29,41,0.97 +269,GET,6,1,0,464,430,9348,1044,1022,1603,2.25,103,100,241,110,100,250,1.07 +270,POST,5,0,797,411,380,9518,877,861,1353,2.13,31,29,80,30,29,41,0.97 +271,GET,2,5,0,191,180,321,486,450,9237,2.54,296,290,561,421,410,892,1.42 +272,POST,15,0,187,1211,1182,2524,2500,2424,11371,2.06,31,29,121,30,29,71,0.97 +273,GET,6,5,0,487,450,9217,1068,1052,1633,2.19,292,290,441,444,411,9718,1.52 +274,POST,13,0,1947,924,901,1483,2045,1983,11030,2.21,31,29,41,30,29,41,0.97 +275,GET,10,2,0,728,691,9889,1631,1592,10139,2.24,154,150,470,178,170,351,1.16 +276,POST,5,0,918,395,371,2886,904,861,14958,2.29,31,29,130,30,29,80,0.97 +277,GET,6,3,0,447,430,772,1103,1071,10299,2.47,200,190,341,265,260,441,1.32 +278,GET,9,4,0,642,621,942,1509,1472,10559,2.35,245,240,371,335,330,591,1.37 +279,GET,12,5,0,837,821,1733,1965,1943,3136,2.35,300,290,541,438,410,9719,1.46 +280,POST,14,0,1617,1106,1082,1934,2284,2225,11021,2.07,31,29,151,47,29,8526,1.52 +281,GET,3,5,0,249,240,511,645,630,1693,2.59,295,290,541,420,410,782,1.42 +282,GET,15,0,0,1190,1152,2094,2463,2374,11211,2.07,31,29,41,30,29,41,0.97 +283,POST,11,0,114,793,771,1332,1767,1723,10379,2.23,31,29,41,30,29,41,0.97 +284,GET,12,5,0,871,821,9919,1976,1933,10580,2.27,298,290,591,423,410,732,1.42 +285,POST,8,0,1446,616,581,9768,1336,1302,2074,2.17,31,29,80,30,29,41,0.97 +286,GET,15,0,0,1210,1162,10089,2430,2364,11401,2.01,31,29,100,30,29,41,0.97 +287,POST,14,0,1714,1105,1082,1804,2323,2234,18725,2.10,31,29,50,30,29,100,0.97 +288,POST,16,0,207,1281,1242,3737,2657,2575,11601,2.07,31,29,41,30,29,41,0.97 +289,POST,5,0,873,391,380,691,881,861,1352,2.25,31,29,100,30,29,90,0.97 +290,POST,7,0,149,525,510,781,1289,1172,48190,2.46,31,29,41,30,29,41,0.97 +291,GET,13,5,0,911,891,1613,2157,2094,12654,2.37,311,290,8826,421,410,962,1.35 +292,POST,6,0,166,447,430,621,1026,991,11121,2.30,31,29,41,30,29,40,0.97 +293,POST,5,0,477,393,380,611,899,871,9878,2.29,31,29,41,30,29,41,0.97 +294,POST,12,0,766,893,832,4088,1906,1853,12533,2.13,31,29,81,30,29,41,0.97 +295,POST,9,0,1803,684,631,18775,1450,1423,3887,2.12,31,29,101,31,29,101,1.00 +296,POST,7,0,1940,523,510,1042,1201,1162,10369,2.30,31,29,80,30,29,40,0.97 +297,POST,17,0,1212,1388,1302,2565,2765,2685,12654,1.99,31,29,41,30,29,41,0.97 +298,POST,8,0,770,605,590,952,1362,1312,10370,2.25,31,29,41,30,29,80,0.97 +299,POST,5,0,986,395,380,562,894,871,9437,2.26,31,29,120,30,29,41,0.97 +300,POST,9,0,1144,665,641,1172,1444,1432,2074,2.17,31,29,130,30,29,100,0.97 +301,POST,9,0,509,672,631,9467,1465,1432,10299,2.18,31,29,120,30,29,41,0.97 +302,POST,8,0,227,592,571,802,1357,1302,10289,2.29,31,29,151,30,29,40,0.97 +303,GET,8,1,0,584,561,2905,1391,1323,10349,2.38,107,100,331,109,100,361,1.02 +304,GET,7,2,0,501,490,691,1215,1182,10330,2.43,156,150,541,177,170,380,1.13 +305,POST,4,0,1518,317,301,491,767,741,9939,2.42,31,29,90,30,29,41,0.97 +306,GET,12,0,0,839,811,1423,1954,1873,10831,2.33,31,29,50,30,29,41,0.97 +307,POST,13,0,1524,923,901,1422,2054,1983,11111,2.23,31,29,41,30,29,41,0.97 +308,POST,13,0,1195,946,901,9718,2139,1983,20077,2.26,31,29,41,30,29,41,0.97 +309,GET,15,2,0,1217,1162,13215,2502,2424,11381,2.06,154,150,461,175,170,472,1.14 +310,GET,8,1,0,591,551,9668,1425,1332,19567,2.41,104,100,271,109,100,220,1.05 +311,GET,14,3,0,1125,1092,2063,2363,2284,13715,2.10,198,190,411,267,260,641,1.35 +312,GET,8,5,0,587,561,1112,1378,1342,10139,2.35,296,290,451,437,410,9017,1.48 +313,POST,4,0,2003,372,300,3237,783,721,2244,2.10,31,29,41,30,29,90,0.97 +314,POST,11,0,88,839,762,20919,1840,1703,13155,2.19,31,29,41,30,29,50,0.97 +315,GET,14,0,0,1143,1092,10369,2284,2214,10981,2.00,31,29,41,30,29,41,0.97 +316,POST,16,0,2034,1295,1242,10399,2619,2554,13866,2.02,31,29,130,31,29,41,1.00 +317,POST,5,0,518,396,380,681,895,861,10039,2.26,31,29,41,30,29,40,0.97 +318,POST,13,0,1986,953,901,12793,2028,1983,10771,2.13,32,29,70,30,29,70,0.94 +319,GET,9,0,0,637,621,972,1455,1412,10069,2.28,31,29,80,30,29,41,0.97 +320,POST,7,0,1425,525,501,771,1196,1162,9999,2.28,31,29,131,30,29,41,0.97 +321,GET,8,5,0,579,561,912,1367,1332,10259,2.36,294,280,722,419,410,1091,1.43 +322,POST,13,0,1197,928,901,1573,2045,1983,13625,2.20,31,29,41,30,29,41,0.97 +323,GET,14,4,0,1140,1091,10239,2336,2294,3446,2.05,246,240,431,350,321,8736,1.42 +324,GET,14,1,0,1121,1091,1594,2504,2304,21541,2.23,107,100,471,110,100,341,1.03 +325,POST,17,0,118,1398,1302,10870,2730,2665,11472,1.95,31,29,41,30,29,41,0.97 +326,POST,9,0,933,815,641,76935,1479,1432,13265,1.81,31,29,41,30,29,80,0.97 +327,GET,10,2,0,720,701,1223,1639,1593,10590,2.28,154,150,661,184,170,2716,1.19 +328,GET,4,1,0,309,290,501,766,741,1142,2.48,103,100,271,109,100,211,1.06 +329,POST,10,0,795,715,701,1233,1622,1582,10670,2.27,31,29,41,30,29,100,0.97 +330,GET,5,3,0,400,370,9287,923,911,1423,2.31,199,190,411,264,260,531,1.33 +331,GET,3,2,0,268,240,9247,638,630,1052,2.38,153,140,371,177,170,300,1.16 +332,POST,7,0,2020,550,511,9357,1179,1162,1863,2.14,31,29,150,30,29,41,0.97 +333,GET,11,0,0,791,751,9628,1764,1693,10389,2.23,32,29,70,30,29,80,0.94 +334,POST,7,0,634,523,510,772,1211,1172,9948,2.32,31,29,41,30,29,50,0.97 +335,GET,13,3,0,913,891,1473,2146,2083,10770,2.35,202,190,411,267,260,561,1.32 +336,POST,7,0,333,531,510,3136,1209,1162,10280,2.28,31,29,41,31,29,100,1.00 +337,GET,14,0,0,1137,1092,10240,2287,2214,11201,2.01,31,29,41,31,29,90,1.00 +338,POST,17,0,1946,1417,1312,10770,3309,2665,28042,2.34,31,29,101,30,29,50,0.97 +339,GET,12,3,0,844,821,2244,1981,1933,13154,2.35,199,190,812,283,260,8767,1.42 +340,POST,16,0,856,1273,1242,2304,2639,2545,12854,2.07,31,29,130,30,29,41,0.97 +341,GET,15,5,0,1194,1152,3777,2539,2454,12022,2.13,294,290,611,420,410,801,1.43 +342,POST,11,0,92,778,761,1332,1756,1713,10380,2.26,31,29,90,30,29,40,0.97 +343,GET,2,2,0,187,180,410,441,430,731,2.36,155,150,281,175,170,331,1.13 +344,GET,12,4,0,863,821,11090,2000,1944,10660,2.32,249,240,401,328,320,531,1.32 +345,GET,15,5,0,1211,1162,10089,2474,2404,11571,2.04,310,280,9278,422,410,762,1.36 +346,GET,7,3,0,508,490,751,1224,1192,10019,2.41,199,190,320,270,260,2425,1.36 +347,POST,9,0,805,661,641,1032,1456,1442,2204,2.20,31,29,50,31,29,100,1.00 +348,POST,15,0,1725,1233,1182,10750,2504,2424,11171,2.03,31,29,131,30,29,41,0.97 +349,POST,15,0,130,1243,1192,1964,2477,2424,11371,1.99,31,29,41,30,29,80,0.97 +350,GET,2,2,0,189,180,451,439,430,701,2.32,153,150,310,176,170,350,1.15 +351,GET,5,0,0,398,370,9387,894,881,1353,2.25,31,29,51,30,29,80,0.97 +352,GET,3,5,0,248,240,631,663,631,9608,2.67,292,280,501,423,410,752,1.45 +353,POST,15,0,1094,1213,1182,2104,2477,2414,11521,2.04,31,29,41,30,29,41,0.97 +354,POST,14,0,2042,1126,1082,9938,2283,2224,11432,2.03,31,29,41,30,29,40,0.97 +355,POST,11,0,1198,804,761,10089,1741,1703,10650,2.17,31,29,140,31,29,71,1.00 +356,POST,14,0,1935,1129,1091,10019,2284,2214,12363,2.02,31,29,130,30,29,40,0.97 +357,POST,15,0,774,1249,1182,15118,2559,2414,21631,2.05,31,29,41,31,29,100,1.00 +358,GET,5,2,0,385,371,952,950,902,12073,2.47,155,150,472,178,170,481,1.15 +359,GET,3,1,0,250,240,441,674,651,9828,2.70,103,100,270,110,100,210,1.07 +360,POST,7,0,1242,523,500,862,1212,1162,11772,2.32,31,29,141,30,29,90,0.97 +361,GET,5,5,0,381,370,671,985,931,10159,2.59,293,290,501,424,420,852,1.45 +362,POST,14,0,1266,1129,1082,10249,2279,2224,12122,2.02,31,29,41,30,29,41,0.97 +363,GET,7,1,0,511,490,851,1243,1192,10389,2.43,106,100,310,111,100,211,1.05 +364,GET,2,4,0,186,180,321,475,450,10900,2.55,250,240,531,330,320,611,1.32 +365,GET,9,2,0,639,621,1122,1504,1462,10279,2.35,153,150,270,176,170,341,1.15 +366,POST,15,0,1065,1248,1182,10130,2498,2434,11552,2.00,31,29,101,31,29,41,1.00 +367,GET,13,4,0,916,891,1523,2136,2043,10800,2.33,246,240,481,391,320,27942,1.59 +368,POST,17,0,1149,1378,1293,2625,2761,2665,13015,2.00,31,29,80,30,29,41,0.97 +369,GET,14,4,0,1124,1092,1783,2344,2284,11031,2.09,248,240,561,335,330,642,1.35 +370,GET,10,0,0,735,691,10069,1594,1552,10810,2.17,31,29,41,30,29,41,0.97 +371,GET,2,2,0,187,180,320,442,431,692,2.36,156,150,301,176,170,361,1.13 +372,POST,14,0,1271,1126,1082,9958,2269,2214,4759,2.02,31,29,90,30,29,41,0.97 +373,POST,13,0,1649,946,902,9778,2032,1973,10630,2.15,31,29,41,31,29,100,1.00 +374,GET,14,0,0,1142,1102,10048,2279,2215,11161,2.00,31,29,41,30,29,41,0.97 +375,POST,4,0,2008,321,310,501,763,731,9878,2.38,31,29,140,30,29,41,0.97 +376,GET,10,3,0,713,691,1142,1621,1593,2275,2.27,199,190,390,263,260,551,1.32 +377,POST,9,0,1136,669,631,9888,1473,1432,10730,2.20,31,29,100,30,29,41,0.97 +378,GET,3,5,0,248,240,551,641,631,991,2.58,296,280,912,473,410,10761,1.60 +379,POST,8,0,1121,590,570,1102,1405,1302,11542,2.38,31,29,70,30,29,41,0.97 +380,POST,10,0,1605,758,691,3257,1615,1572,12744,2.13,31,29,90,30,29,40,0.97 +381,POST,9,0,610,674,631,12243,1445,1423,2185,2.14,49,29,9006,30,29,41,0.61 +382,POST,11,0,1766,782,761,1192,1747,1703,10690,2.23,31,29,41,30,29,80,0.97 +383,POST,17,0,1631,1388,1302,10801,2732,2665,11952,1.97,31,29,41,31,29,90,1.00 +384,GET,8,5,0,607,561,9268,1382,1342,11191,2.28,294,290,651,421,410,1042,1.43 +385,POST,10,0,1575,751,701,4038,1626,1583,11702,2.17,31,29,41,30,29,90,0.97 +386,GET,2,2,0,208,180,9298,440,430,731,2.12,154,150,361,182,180,400,1.18 +387,GET,15,3,0,1206,1162,3677,2492,2434,11391,2.07,199,190,361,264,260,512,1.33 +388,GET,6,1,0,469,440,9227,1049,1021,3787,2.24,106,100,371,111,100,210,1.05 +389,GET,10,3,0,717,691,1112,1624,1593,2294,2.26,198,190,341,264,260,391,1.33 +390,GET,6,0,0,446,431,771,1035,1001,9708,2.32,31,29,41,31,29,41,1.00 +391,POST,5,0,942,394,380,692,896,862,10079,2.27,31,29,140,30,29,41,0.97 +392,GET,10,0,0,712,681,1372,1594,1552,10380,2.24,31,29,120,30,29,41,0.97 +393,GET,3,4,0,250,240,470,666,630,9498,2.66,250,240,440,325,320,561,1.30 +394,POST,6,0,372,452,440,882,1024,991,9607,2.27,31,29,41,30,29,41,0.97 +395,POST,8,0,843,593,581,2745,1357,1312,10439,2.29,31,29,270,30,29,41,0.97 +396,POST,16,0,971,1297,1242,10429,2614,2554,4639,2.02,31,29,131,30,29,41,0.97 +397,POST,13,0,1993,929,902,1362,2041,1984,11442,2.20,31,29,41,37,29,2254,1.19 +398,GET,10,1,0,717,691,1714,1798,1583,13876,2.51,105,100,501,109,100,391,1.04 +399,GET,2,4,0,193,180,611,454,440,1614,2.35,250,240,551,385,320,10190,1.54 +400,GET,6,1,0,454,440,992,1048,1031,1964,2.31,104,100,250,110,100,230,1.06 +401,GET,4,0,0,307,290,592,754,741,1392,2.46,31,29,41,38,29,51,1.23 +402,GET,9,0,0,677,630,15930,1458,1412,10399,2.15,40,29,51,30,29,81,0.75 +403,POST,10,0,729,723,691,1182,1602,1562,10400,2.22,50,40,101,50,49,61,1.00 +404,GET,14,2,0,1182,1102,18205,2340,2274,12082,1.98,153,140,420,175,170,441,1.14 +405,GET,9,1,0,658,621,9739,1470,1453,2054,2.23,104,100,190,127,100,8676,1.22 +406,POST,8,0,80,602,581,1122,1392,1302,10870,2.31,31,29,70,30,29,41,0.97 +407,GET,13,2,0,918,891,1793,2129,2063,10830,2.32,154,150,390,179,170,391,1.16 +408,POST,13,0,167,925,901,1412,2054,1984,11190,2.22,31,29,90,30,29,41,0.97 +409,POST,16,0,321,1275,1242,2245,2620,2554,11441,2.05,31,29,41,30,29,41,0.97 +410,POST,9,0,125,665,631,1152,1469,1423,10470,2.21,31,29,41,30,29,80,0.97 +411,GET,5,5,0,384,380,731,972,942,1333,2.53,296,290,581,427,420,882,1.44 +412,POST,5,0,1533,410,380,8927,873,861,1383,2.13,31,29,41,30,29,41,0.97 +413,POST,6,0,2020,446,430,591,1024,992,10110,2.30,31,29,41,30,29,70,0.97 +414,GET,9,2,0,652,631,1162,1506,1452,11101,2.31,156,150,311,182,170,360,1.17 +415,POST,10,0,483,720,701,1042,1610,1572,10781,2.24,31,29,71,30,29,41,0.97 +416,POST,14,0,755,1131,1082,9988,2339,2224,11141,2.07,32,29,81,32,29,71,1.00 +417,POST,10,0,1476,1119,902,23113,1601,1572,5540,1.43,71,29,20268,32,29,191,0.45 +418,POST,4,0,75,317,301,681,752,721,1523,2.37,31,29,41,30,29,80,0.97 +419,GET,5,0,0,402,370,10440,888,881,1323,2.21,31,29,41,30,29,41,0.97 +420,POST,13,0,1834,925,901,1643,2060,1994,10831,2.23,31,29,41,30,29,41,0.97 +421,POST,11,0,1535,781,761,1152,1731,1693,10910,2.22,31,29,41,31,29,41,1.00 +422,POST,4,0,219,333,300,9618,748,722,1142,2.25,31,29,41,30,29,41,0.97 +423,POST,10,0,725,714,701,1002,1617,1572,10479,2.26,31,29,80,30,29,41,0.97 +424,POST,9,0,496,650,631,931,1445,1422,2124,2.22,31,29,80,30,29,41,0.97 +425,GET,5,4,0,388,370,842,930,921,1303,2.40,266,240,9057,328,320,932,1.23 +426,GET,4,0,0,306,290,551,740,731,1122,2.42,31,29,41,47,29,8416,1.52 +427,POST,8,0,1722,585,570,862,1364,1312,10570,2.33,31,29,41,30,29,41,0.97 +428,GET,3,1,0,251,240,451,647,641,902,2.58,105,100,211,110,100,260,1.05 +429,POST,5,0,477,409,380,9788,875,861,1312,2.14,31,29,71,30,29,41,0.97 +430,POST,8,0,1216,605,571,8887,1345,1302,1903,2.22,31,29,41,30,29,100,0.97 +431,GET,11,2,0,826,742,9287,1759,1723,3136,2.13,156,150,521,179,170,431,1.15 +432,POST,13,0,1021,919,901,1643,2054,1984,10801,2.24,31,29,41,31,29,100,1.00 +433,GET,3,3,0,251,240,501,638,630,902,2.54,219,190,9608,268,260,561,1.22 +434,POST,14,0,1202,1110,1082,2094,2291,2204,11521,2.06,31,29,40,30,29,41,0.97 +435,POST,14,0,1201,1109,1082,1713,2281,2213,11431,2.06,31,29,41,30,29,41,0.97 +436,GET,9,0,0,653,631,922,1458,1412,10409,2.23,31,29,41,31,29,90,1.00 +437,GET,5,2,0,386,371,601,951,901,17032,2.46,155,150,331,180,170,381,1.16 +438,GET,14,3,0,1142,1092,11040,2345,2284,11040,2.05,201,190,360,270,260,2835,1.34 +439,POST,11,0,500,863,761,9648,1757,1703,17513,2.04,31,29,50,30,29,81,0.97 +440,GET,8,5,0,582,570,1032,1377,1332,11291,2.37,296,290,641,425,420,982,1.44 +441,GET,10,5,0,729,691,10028,1640,1603,11020,2.25,297,290,421,422,410,641,1.42 +442,GET,2,0,0,190,180,341,432,420,671,2.27,31,29,41,30,29,80,0.97 +443,GET,4,2,0,309,300,661,758,751,1272,2.45,158,150,281,181,170,371,1.15 +444,GET,8,0,0,598,561,11211,1302,1292,1904,2.18,31,29,41,48,29,8826,1.55 +445,POST,6,0,180,452,440,701,1009,1001,1513,2.23,31,29,41,30,29,41,0.97 +446,GET,13,1,0,918,901,1793,2143,2093,5821,2.33,105,100,241,110,100,230,1.05 +447,GET,14,5,0,1142,1091,10008,2341,2284,11331,2.05,297,290,541,423,410,742,1.42 +448,GET,2,3,0,190,180,391,465,460,762,2.45,201,190,300,266,260,401,1.32 +449,GET,7,4,0,577,491,10399,1228,1212,2324,2.13,276,240,11782,334,320,741,1.21 +450,POST,17,0,229,1409,1302,10239,2744,2665,16320,1.95,31,29,41,30,29,41,0.97 +451,POST,9,0,1180,667,641,1132,1448,1432,2325,2.17,31,29,110,30,29,41,0.97 +452,POST,16,0,1773,1271,1232,2124,2653,2564,11522,2.09,31,29,401,30,29,41,0.97 +453,GET,13,5,0,913,892,1523,2173,2093,12704,2.38,296,290,521,423,411,761,1.43 +454,GET,8,1,0,595,571,1022,1373,1312,10409,2.31,106,100,180,110,100,210,1.04 +455,POST,13,0,1681,927,901,1543,2061,1993,11181,2.22,31,29,140,30,29,90,0.97 +456,POST,14,0,1140,1126,1082,10239,2268,2214,11141,2.01,31,29,41,30,29,80,0.97 +457,POST,12,0,976,892,851,9748,1905,1833,24085,2.14,31,29,41,30,29,41,0.97 +458,GET,13,4,0,923,892,3377,2144,2093,11531,2.32,250,240,471,336,330,731,1.34 +459,GET,4,5,0,310,300,511,780,771,1132,2.52,312,290,9067,420,410,692,1.35 +460,GET,11,2,0,779,751,1232,1784,1733,10610,2.29,154,150,381,180,170,371,1.17 +461,GET,9,4,0,649,631,972,1518,1472,10159,2.34,249,240,381,328,320,511,1.32 +462,GET,9,0,0,645,630,1042,1464,1422,9979,2.27,31,29,41,30,29,41,0.97 +463,POST,12,0,1573,885,832,11561,1894,1823,21451,2.14,31,29,141,30,29,41,0.97 +464,GET,3,3,0,249,240,500,664,630,10740,2.67,204,190,561,271,260,551,1.33 +465,POST,6,0,1909,454,430,3146,1025,991,10099,2.26,31,29,41,30,29,91,0.97 +466,GET,6,3,0,450,440,741,1101,1062,10179,2.45,202,190,351,267,260,421,1.32 +467,POST,4,0,756,314,300,461,766,732,9537,2.44,31,29,140,30,29,41,0.97 +468,GET,8,0,0,586,571,1002,1337,1292,10289,2.28,31,29,130,31,29,41,1.00 +469,POST,4,0,1124,314,300,471,745,731,1002,2.37,31,29,41,30,29,90,0.97 +470,POST,6,0,660,449,440,721,1007,991,1383,2.24,31,29,90,30,29,40,0.97 +471,POST,15,0,180,1230,1182,10169,2486,2424,11461,2.02,48,29,8676,30,29,41,0.62 +472,GET,3,4,0,245,240,480,641,630,962,2.62,248,240,551,328,320,531,1.32 +473,GET,12,0,0,1079,811,10169,3060,1863,25738,2.84,36,29,101,33,29,70,0.92 +474,POST,10,0,966,1141,902,24005,1925,1572,21891,1.69,31,29,81,30,29,60,0.97 +475,POST,9,0,1627,659,641,1583,1496,1422,25427,2.27,31,29,100,30,29,41,0.97 +476,GET,3,5,0,249,240,511,817,631,22232,3.28,532,431,1112,654,410,4338,1.23 +477,POST,15,0,1528,1578,1182,21230,2789,2404,22011,1.77,31,29,80,30,29,60,0.97 +478,POST,9,0,254,668,641,1653,1464,1422,12734,2.19,31,29,41,31,29,41,1.00 +479,POST,14,0,2030,1133,1082,11331,2309,2204,19116,2.04,31,29,41,30,29,41,0.97 +480,POST,6,0,371,494,431,17873,1006,991,1713,2.04,31,29,101,31,29,41,1.00 +481,GET,2,5,0,190,180,360,486,450,10830,2.56,297,290,801,421,410,1172,1.42 +482,POST,14,0,1177,1132,1072,11362,2309,2213,19837,2.04,31,29,80,30,29,41,0.97 +483,GET,13,4,0,957,891,19236,2151,2084,13024,2.25,246,240,641,332,320,762,1.35 +484,GET,13,4,0,987,891,11842,2180,2093,19095,2.21,247,240,561,332,320,721,1.34 +485,POST,6,0,1638,474,430,992,1012,991,3827,2.14,31,29,50,30,29,41,0.97 +486,GET,13,0,0,937,891,11772,2065,2003,11121,2.20,31,29,101,31,29,41,1.00 +487,GET,13,1,0,965,892,17553,2174,2093,21240,2.25,105,100,381,110,100,902,1.05 +488,POST,12,0,1071,876,851,1332,1852,1823,2955,2.11,31,29,41,53,29,11171,1.71 +489,POST,9,0,647,662,641,1052,1509,1432,18945,2.28,31,29,41,30,29,41,0.97 +490,POST,12,0,804,863,841,1413,1896,1823,21150,2.20,31,29,41,30,29,41,0.97 +491,POST,15,0,926,1216,1192,2194,2554,2425,19807,2.10,31,29,41,30,29,41,0.97 +492,GET,11,2,0,790,761,1272,1997,1733,20528,2.53,154,150,782,179,170,621,1.16 +493,POST,10,0,1278,768,701,21330,1608,1572,11762,2.09,31,29,41,30,29,41,0.97 +494,GET,9,4,0,662,621,3757,1565,1472,21140,2.36,249,240,631,352,330,3126,1.41 +495,GET,9,3,0,644,621,2054,1564,1463,13666,2.43,201,190,501,266,260,691,1.32 +496,GET,6,5,0,447,440,892,1128,1051,12213,2.52,294,280,511,420,410,742,1.43 +497,GET,7,3,0,531,490,11642,1206,1192,1754,2.27,248,190,18024,265,260,501,1.07 +498,POST,4,0,1857,314,300,511,746,732,1463,2.38,31,29,41,30,29,100,0.97 +499,GET,10,3,0,761,691,17784,1644,1592,11712,2.16,201,190,381,267,260,572,1.33