diff options
author | AlexSm <alex@ydb.tech> | 2024-01-09 18:56:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-09 18:56:40 +0100 |
commit | e95f266d2a3e48e62015220588a4fd73d5d5a5cb (patch) | |
tree | a8a784b6931fe52ad5f511cfef85af14e5f63991 /library/cpp/http/io | |
parent | 50a65e3b48a82d5b51f272664da389f2e0b0c99a (diff) | |
download | ydb-e95f266d2a3e48e62015220588a4fd73d5d5a5cb.tar.gz |
Library import 6 (#888)
Diffstat (limited to 'library/cpp/http/io')
-rw-r--r-- | library/cpp/http/io/benchmark/main.cpp | 81 | ||||
-rw-r--r-- | library/cpp/http/io/benchmark/ya.make | 11 | ||||
-rw-r--r-- | library/cpp/http/io/headers.cpp | 14 | ||||
-rw-r--r-- | library/cpp/http/io/ya.make | 6 |
4 files changed, 108 insertions, 4 deletions
diff --git a/library/cpp/http/io/benchmark/main.cpp b/library/cpp/http/io/benchmark/main.cpp new file mode 100644 index 0000000000..2a3a07b3bb --- /dev/null +++ b/library/cpp/http/io/benchmark/main.cpp @@ -0,0 +1,81 @@ +#include <library/cpp/http/io/headers.h> + +#include <benchmark/benchmark.h> + +#include <util/stream/str.h> + +void FindHeaderFirstMatch(benchmark::State& state) { + THttpHeaders headers; + headers.AddHeader("Host", "example.com"); + Y_ENSURE(headers.FindHeader("Host")); + for (auto _ : state) { + auto header = headers.FindHeader("Host"); + benchmark::DoNotOptimize(header); + } +} + +void FindHeaderNoMatchSameSize(benchmark::State& state) { + THttpHeaders headers; + for (char c = 'a'; c <= 'z'; ++c) { + headers.AddHeader(TString::Join(c, "aaa"), "some value"); + } + Y_ENSURE(!headers.FindHeader("Host")); + for (auto _ : state) { + auto header = headers.FindHeader("Host"); + benchmark::DoNotOptimize(header); + } +} + +void FindHeaderNoMatchDifferentSizesNoCommonPrefix(benchmark::State& state) { + THttpHeaders headers; + for (char c = 'a'; c <= 'z'; ++c) { // same number of headers as above + headers.AddHeader("aaaaa", "some value"); + } + Y_ENSURE(!headers.FindHeader("Host")); + for (auto _ : state) { + auto header = headers.FindHeader("Host"); + benchmark::DoNotOptimize(header); + } +} + +void FindHeaderNoMatchDifferentSizesCommonPrefix(benchmark::State& state) { + THttpHeaders headers; + for (char c = 'a'; c <= 'z'; ++c) { + headers.AddHeader("Host2", "some value"); + } + Y_ENSURE(!headers.FindHeader("Host")); + for (auto _ : state) { + auto header = headers.FindHeader("Host"); + benchmark::DoNotOptimize(header); + } +} + +void FindHeaderMoreRealisticUseCase(benchmark::State& state) { + TString requestHeaders(R"(Host: yandex.ru +User-Agent: Mozilla/5.0 ... +Accept: */* +Accept-Language: en-US,en;q=0.5 +Accept-Encoding: gzip, deflate, br +Content-Type: text/plain;charset=UTF-8 +Content-Length: 1234 +Origin: https://a.yandex-team.ru +Connection: keep-alive +Referer: https://a.yandex-team.ru/ +Sec-Fetch-Dest: empty +Sec-Fetch-Mode: no-cors +Sec-Fetch-Site: cross-site +TE: trailers)"); + TStringInput stream(requestHeaders); + THttpHeaders headers(&stream); + Y_ENSURE(headers.FindHeader("Content-Type")); + for (auto _ : state) { + auto header = headers.FindHeader("Content-Type"); + benchmark::DoNotOptimize(header); + } +} + +BENCHMARK(FindHeaderFirstMatch); +BENCHMARK(FindHeaderNoMatchSameSize); +BENCHMARK(FindHeaderNoMatchDifferentSizesNoCommonPrefix); +BENCHMARK(FindHeaderNoMatchDifferentSizesCommonPrefix); +BENCHMARK(FindHeaderMoreRealisticUseCase); diff --git a/library/cpp/http/io/benchmark/ya.make b/library/cpp/http/io/benchmark/ya.make new file mode 100644 index 0000000000..6e1d252df0 --- /dev/null +++ b/library/cpp/http/io/benchmark/ya.make @@ -0,0 +1,11 @@ +G_BENCHMARK() + +PEERDIR( + library/cpp/http/io +) + +SRCS( + main.cpp +) + +END() diff --git a/library/cpp/http/io/headers.cpp b/library/cpp/http/io/headers.cpp index 4ec27a29e8..f2baf64021 100644 --- a/library/cpp/http/io/headers.cpp +++ b/library/cpp/http/io/headers.cpp @@ -12,6 +12,13 @@ static inline TStringBuf Trim(const char* b, const char* e) noexcept { return StripString(TStringBuf(b, e)); } +static inline bool HeaderNameEqual(TStringBuf headerName, TStringBuf expectedName) noexcept { + // Most headers names have distinct sizes. + // Size comparison adds small overhead if all headers have the same size (~4% or lower with size = 4), + // but significantly speeds up the case where sizes are different (~4.5x for expectedName.size() = 4 and headerName.size() = 5) + return headerName.size() == expectedName.size() && AsciiCompareIgnoreCase(headerName, expectedName) == 0; +} + THttpInputHeader::THttpInputHeader(const TStringBuf header) { size_t pos = header.find(':'); @@ -65,7 +72,7 @@ bool THttpHeaders::HasHeader(const TStringBuf header) const { const THttpInputHeader* THttpHeaders::FindHeader(const TStringBuf header) const { for (const auto& hdr : Headers_) { - if (AsciiCompareIgnoreCase(hdr.Name(), header) == 0) { + if (HeaderNameEqual(hdr.Name(), header)) { return &hdr; } } @@ -74,7 +81,7 @@ const THttpInputHeader* THttpHeaders::FindHeader(const TStringBuf header) const void THttpHeaders::RemoveHeader(const TStringBuf header) { for (auto h = Headers_.begin(); h != Headers_.end(); ++h) { - if (AsciiCompareIgnoreCase(h->Name(), header) == 0) { + if (HeaderNameEqual(h->Name(), header)) { Headers_.erase(h); return; } @@ -82,8 +89,9 @@ void THttpHeaders::RemoveHeader(const TStringBuf header) { } void THttpHeaders::AddOrReplaceHeader(const THttpInputHeader& header) { + TStringBuf name = header.Name(); for (auto& hdr : Headers_) { - if (AsciiCompareIgnoreCase(hdr.Name(), header.Name()) == 0) { + if (HeaderNameEqual(hdr.Name(), name)) { hdr = header; return; } diff --git a/library/cpp/http/io/ya.make b/library/cpp/http/io/ya.make index 0390aecf55..20e014d011 100644 --- a/library/cpp/http/io/ya.make +++ b/library/cpp/http/io/ya.make @@ -17,7 +17,11 @@ SRCS( END() RECURSE( - fuzz list_codings +) + +RECURSE_FOR_TESTS( + benchmark + fuzz ut ) |