Skip to content

Commit

Permalink
improve substitution formatter parsing performance (envoyproxy#35498)
Browse files Browse the repository at this point in the history
Commit Message: improve substitution formatter parsing performance
Additional Description:

See envoyproxy#35466

Previous parsing performance result:
```
---------------------------------------------------------------------------
Benchmark                                 Time             CPU   Iterations
---------------------------------------------------------------------------
BM_AccessLogFormatterSetup            75744 ns        75605 ns         9401
```

Latest parsing performance result:
```
---------------------------------------------------------------------------
Benchmark                                 Time             CPU   Iterations
---------------------------------------------------------------------------
BM_AccessLogFormatterSetup             8932 ns         8917 ns        78153
```

Risk Level: mid. Core code change.
Testing: unit.
Docs Changes: n/a.
Release Notes: no behavior change.
Platform Specific Features: n/a.

---------

Signed-off-by: wbpcode <[email protected]>
  • Loading branch information
wbpcode authored Aug 2, 2024
1 parent 37bdbd1 commit 6c645a1
Show file tree
Hide file tree
Showing 20 changed files with 370 additions and 390 deletions.
4 changes: 2 additions & 2 deletions envoy/formatter/substitution_formatter_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ template <class FormatterContext> class CommandParserBase {
* @return FormattterProviderPtr substitution provider for the parsed command.
*/
virtual FormatterProviderBasePtr<FormatterContext>
parse(const std::string& command, const std::string& command_arg,
absl::optional<size_t>& max_length) const PURE;
parse(absl::string_view command, absl::string_view command_arg,
absl::optional<size_t> max_length) const PURE;
};

template <class FormatterContext>
Expand Down
89 changes: 39 additions & 50 deletions source/common/formatter/http_specific_formatter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ AccessLogTypeFormatter::formatValueWithContext(const HttpFormatterContext& conte
return ValueUtil::stringValue(AccessLogType_Name(context.accessLogType()));
}

HeaderFormatter::HeaderFormatter(const std::string& main_header,
const std::string& alternative_header,
HeaderFormatter::HeaderFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: main_header_(main_header), alternative_header_(alternative_header), max_length_(max_length) {}

Expand Down Expand Up @@ -81,8 +81,8 @@ ProtobufWkt::Value HeaderFormatter::formatValue(const Http::HeaderMap& headers)
return ValueUtil::stringValue(std::string(val));
}

ResponseHeaderFormatter::ResponseHeaderFormatter(const std::string& main_header,
const std::string& alternative_header,
ResponseHeaderFormatter::ResponseHeaderFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: HeaderFormatter(main_header, alternative_header, max_length) {}

Expand All @@ -98,8 +98,8 @@ ResponseHeaderFormatter::formatValueWithContext(const HttpFormatterContext& cont
return HeaderFormatter::formatValue(context.responseHeaders());
}

RequestHeaderFormatter::RequestHeaderFormatter(const std::string& main_header,
const std::string& alternative_header,
RequestHeaderFormatter::RequestHeaderFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: HeaderFormatter(main_header, alternative_header, max_length) {}

Expand All @@ -115,8 +115,8 @@ RequestHeaderFormatter::formatValueWithContext(const HttpFormatterContext& conte
return HeaderFormatter::formatValue(context.requestHeaders());
}

ResponseTrailerFormatter::ResponseTrailerFormatter(const std::string& main_header,
const std::string& alternative_header,
ResponseTrailerFormatter::ResponseTrailerFormatter(absl::string_view main_header,
absl::string_view alternative_header,
absl::optional<size_t> max_length)
: HeaderFormatter(main_header, alternative_header, max_length) {}

Expand Down Expand Up @@ -298,96 +298,85 @@ BuiltInHttpCommandParser::getKnownFormatters() {
FormatterProviderLookupTbl,
{{"REQ",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;

THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<RequestHeaderFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<RequestHeaderFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"RESP",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;

THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<ResponseHeaderFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<ResponseHeaderFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"TRAILER",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;

THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<ResponseTrailerFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<ResponseTrailerFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"LOCAL_REPLY_BODY",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<LocalReplyBodyFormatter>();
}}},
{"ACCESS_LOG_TYPE",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<AccessLogTypeFormatter>();
}}},
{"GRPC_STATUS",
{CommandSyntaxChecker::PARAMS_OPTIONAL,
[](const std::string& format, const absl::optional<size_t>&) {
[](absl::string_view format, absl::optional<size_t>) {
return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(),
GrpcStatusFormatter::parseFormat(format));
}}},
{"GRPC_STATUS_NUMBER",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, const absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(),
GrpcStatusFormatter::Number);
}}},
{"REQUEST_HEADERS_BYTES",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<HeadersByteSizeFormatter>(
HeadersByteSizeFormatter::HeaderType::RequestHeaders);
}}},
{"RESPONSE_HEADERS_BYTES",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<HeadersByteSizeFormatter>(
HeadersByteSizeFormatter::HeaderType::ResponseHeaders);
}}},
{"RESPONSE_TRAILERS_BYTES",
{CommandSyntaxChecker::COMMAND_ONLY,
[](const std::string&, absl::optional<size_t>&) {
[](absl::string_view, absl::optional<size_t>) {
return std::make_unique<HeadersByteSizeFormatter>(
HeadersByteSizeFormatter::HeaderType::ResponseTrailers);
}}},
{"STREAM_INFO_REQ",
{CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
[](const std::string& format, absl::optional<size_t>& max_length) {
std::string main_header, alternative_header;
THROW_IF_NOT_OK(SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header,
alternative_header));

return std::make_unique<RequestHeaderFormatter>(main_header, alternative_header,
max_length);
[](absl::string_view format, absl::optional<size_t> max_length) {
auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
THROW_IF_STATUS_NOT_OK(result, throw);
return std::make_unique<RequestHeaderFormatter>(result.value().first,
result.value().second, max_length);
}}},
{"TRACE_ID",
{CommandSyntaxChecker::COMMAND_ONLY, [](const std::string&, absl::optional<size_t>&) {
{CommandSyntaxChecker::COMMAND_ONLY, [](absl::string_view, absl::optional<size_t>) {
return std::make_unique<TraceIDFormatter>();
}}}});
}

FormatterProviderPtr BuiltInHttpCommandParser::parse(const std::string& command,
const std::string& subcommand,
absl::optional<size_t>& max_length) const {
FormatterProviderPtr BuiltInHttpCommandParser::parse(absl::string_view command,
absl::string_view subcommand,
absl::optional<size_t> max_length) const {
const FormatterProviderLookupTbl& providers = getKnownFormatters();

auto it = providers.find(command);
Expand Down
14 changes: 7 additions & 7 deletions source/common/formatter/http_specific_formatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class AccessLogTypeFormatter : public FormatterProvider {

class HeaderFormatter {
public:
HeaderFormatter(const std::string& main_header, const std::string& alternative_header,
HeaderFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

protected:
Expand Down Expand Up @@ -97,7 +97,7 @@ class HeadersByteSizeFormatter : public FormatterProvider {
*/
class RequestHeaderFormatter : public FormatterProvider, HeaderFormatter {
public:
RequestHeaderFormatter(const std::string& main_header, const std::string& alternative_header,
RequestHeaderFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

// FormatterProvider
Expand All @@ -114,7 +114,7 @@ class RequestHeaderFormatter : public FormatterProvider, HeaderFormatter {
*/
class ResponseHeaderFormatter : public FormatterProvider, HeaderFormatter {
public:
ResponseHeaderFormatter(const std::string& main_header, const std::string& alternative_header,
ResponseHeaderFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

// FormatterProvider
Expand All @@ -131,7 +131,7 @@ class ResponseHeaderFormatter : public FormatterProvider, HeaderFormatter {
*/
class ResponseTrailerFormatter : public FormatterProvider, HeaderFormatter {
public:
ResponseTrailerFormatter(const std::string& main_header, const std::string& alternative_header,
ResponseTrailerFormatter(absl::string_view main_header, absl::string_view alternative_header,
absl::optional<size_t> max_length);

// FormatterProvider
Expand Down Expand Up @@ -205,12 +205,12 @@ class BuiltInHttpCommandParser : public CommandParser {
BuiltInHttpCommandParser() = default;

// CommandParser
FormatterProviderPtr parse(const std::string& command, const std::string& subcommand,
absl::optional<size_t>& max_length) const override;
FormatterProviderPtr parse(absl::string_view command, absl::string_view subcommand,
absl::optional<size_t> max_length) const override;

private:
using FormatterProviderCreateFunc =
std::function<FormatterProviderPtr(const std::string&, absl::optional<size_t>&)>;
std::function<FormatterProviderPtr(absl::string_view, absl::optional<size_t>)>;

using FormatterProviderLookupTbl =
absl::flat_hash_map<absl::string_view, std::pair<CommandSyntaxChecker::CommandSyntaxFlags,
Expand Down
Loading

0 comments on commit 6c645a1

Please sign in to comment.