From a67dfa9e59f1de29518fd51b72289b595131e23b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 23 Jan 2025 12:21:12 +0100 Subject: [PATCH] cgi/Address: cache the GetChildId() value This again eliminates a good amount of per-request overhead. --- src/ResourceAddress.cxx | 27 ++++++++++++++++++++++++++- src/ResourceAddress.hxx | 3 +++ src/cgi/Address.cxx | 14 ++++++++++++++ src/cgi/Address.hxx | 12 ++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/ResourceAddress.cxx b/src/ResourceAddress.cxx index 174f189ec..06c966825 100644 --- a/src/ResourceAddress.cxx +++ b/src/ResourceAddress.cxx @@ -238,6 +238,27 @@ ResourceAddress::SaveBase(AllocatorPtr alloc, gcc_unreachable(); } +inline void +ResourceAddress::PostCacheStore(AllocatorPtr alloc) noexcept +{ + switch (type) { + case Type::NONE: + case Type::PIPE: + break; + + case Type::CGI: + case Type::FASTCGI: + case Type::WAS: + GetCgi().PostCacheStore(alloc); + break; + + case Type::LOCAL: + case Type::HTTP: + case Type::LHTTP: + break; + } +} + void ResourceAddress::CacheStore(AllocatorPtr alloc, const ResourceAddress &src, @@ -246,6 +267,7 @@ ResourceAddress::CacheStore(AllocatorPtr alloc, { if (base == nullptr) { CopyFrom(alloc, src); + PostCacheStore(alloc); return; } else if (const char *tail = base_tail(uri, base)) { /* we received a valid BASE packet - store only the base @@ -255,6 +277,7 @@ ResourceAddress::CacheStore(AllocatorPtr alloc, /* when the response is expandable, skip appending the tail URI, don't call SaveBase() */ CopyFrom(alloc, src); + PostCacheStore(alloc); return; } @@ -267,8 +290,10 @@ ResourceAddress::CacheStore(AllocatorPtr alloc, } *this = src.SaveBase(alloc, tail); - if (IsDefined()) + if (IsDefined()) { + PostCacheStore(alloc); return; + } /* the tail could not be applied to the address, so this is a base mismatch */ diff --git a/src/ResourceAddress.hxx b/src/ResourceAddress.hxx index ba84779b7..9d8bbc1cb 100644 --- a/src/ResourceAddress.hxx +++ b/src/ResourceAddress.hxx @@ -335,4 +335,7 @@ public: * Throws std::runtime_error on error. */ void Expand(AllocatorPtr alloc, const MatchData &match_data); + +private: + void PostCacheStore(AllocatorPtr alloc) noexcept; }; diff --git a/src/cgi/Address.cxx b/src/cgi/Address.cxx index 95b6c3239..bfcb57dd7 100644 --- a/src/cgi/Address.cxx +++ b/src/cgi/Address.cxx @@ -38,6 +38,7 @@ CgiAddress::CgiAddress(AllocatorPtr alloc, const CgiAddress &src) noexcept query_string(alloc.CheckDup(src.query_string)), document_root(alloc.CheckDup(src.document_root)), address_list(alloc, src.address_list), + cached_child_id(alloc.Dup(src.cached_child_id)), parallelism(src.parallelism), concurrency(src.concurrency), disposable(src.disposable), @@ -50,6 +51,16 @@ CgiAddress::CgiAddress(AllocatorPtr alloc, const CgiAddress &src) noexcept { } +void +CgiAddress::PostCacheStore(AllocatorPtr alloc) noexcept +{ + /* cache the GetChildId() call only if we expect future calls + to have the same result, i.e. none of the relevant fields + are "expandable" */ + if ((action != nullptr || !expand_path) && !IsChildExpandable()) + cached_child_id = GetChildId(alloc); +} + [[gnu::pure]] static bool HasTrailingSlash(const char *p) noexcept @@ -93,6 +104,9 @@ CgiAddress::GetURI(AllocatorPtr alloc) const noexcept StringWithHash CgiAddress::GetChildId(AllocatorPtr alloc) const noexcept { + if (!cached_child_id.IsNull()) + return cached_child_id; + std::size_t hash = options.GetHash(); PoolStringBuilder<256> b; diff --git a/src/cgi/Address.hxx b/src/cgi/Address.hxx index a441c3443..c8a61dd1a 100644 --- a/src/cgi/Address.hxx +++ b/src/cgi/Address.hxx @@ -7,6 +7,7 @@ #include "spawn/ChildOptions.hxx" #include "cluster/AddressList.hxx" #include "adata/ExpandableStringList.hxx" +#include "util/StringWithHash.hxx" #include @@ -48,6 +49,8 @@ struct CgiAddress { */ AddressList address_list; + StringWithHash cached_child_id{nullptr}; + /** * The maximum number of parallel child processes of this * kind. @@ -93,6 +96,7 @@ struct CgiAddress { uri(src.uri), script_name(src.script_name), path_info(src.path_info), query_string(src.query_string), document_root(src.document_root), address_list(shallow_copy, src.address_list), + cached_child_id(src.cached_child_id), concurrency(src.concurrency), disposable(src.disposable), request_uri_verbatim(src.request_uri_verbatim), @@ -111,6 +115,8 @@ struct CgiAddress { CgiAddress &operator=(const CgiAddress &) = delete; + void PostCacheStore(AllocatorPtr alloc) noexcept; + [[gnu::pure]] const char *GetURI(AllocatorPtr alloc) const noexcept; @@ -215,6 +221,12 @@ struct CgiAddress { params.IsExpandable(); } + [[gnu::pure]] + bool IsChildExpandable() const noexcept { + return options.IsExpandable() || + args.IsExpandable(); + } + /** * Throws std::runtime_error on error. */