From 9dae7b7f7368cee85cee07d330186d0deb91c317 Mon Sep 17 00:00:00 2001 From: Craig Taylor Date: Fri, 17 Apr 2026 10:45:09 -0600 Subject: [PATCH 1/2] Reduce TLS handshake contention on SSLCertContext Replace std::mutex with ts::bravo::shared_mutex on SSLCertContext to allow true reader concurrency for getCtx() on the TLS handshake hot path. setCtx() (config reload only) takes an exclusive lock. Memory trade-off: BRAVO uses 256 cache-line-aligned reader slots (~16 KB per mutex) vs ~40 bytes for std::mutex or ~56 bytes for std::shared_mutex on Linux. For 256 certificates this is ~4 MB (vs 10 KB / 14 KB), a modest cost relative to the SSL_CTX objects themselves but worth noting for deployments with many certs. --- src/iocore/net/P_SSLCertLookup.h | 6 +++--- src/iocore/net/SSLCertLookup.cc | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/iocore/net/P_SSLCertLookup.h b/src/iocore/net/P_SSLCertLookup.h index b40baa74c30..2bf9e57d618 100644 --- a/src/iocore/net/P_SSLCertLookup.h +++ b/src/iocore/net/P_SSLCertLookup.h @@ -26,10 +26,10 @@ #include "iocore/eventsystem/ConfigProcessor.h" #include "iocore/net/SSLTypes.h" #include "records/RecCore.h" +#include "tsutil/Bravo.h" #include #include -#include #include #include @@ -94,8 +94,8 @@ using shared_ssl_ticket_key_block = std::shared_ptr; */ struct SSLCertContext { private: - mutable std::mutex ctx_mutex; - shared_SSL_CTX ctx; + mutable ts::bravo::shared_mutex ctx_mutex; + shared_SSL_CTX ctx; public: SSLCertContext() : ctx_mutex(), ctx(nullptr), opt(SSLCertContextOption::OPT_NONE), userconfig(nullptr), keyblock(nullptr) {} diff --git a/src/iocore/net/SSLCertLookup.cc b/src/iocore/net/SSLCertLookup.cc index fc715fc5f90..e13e28e1063 100644 --- a/src/iocore/net/SSLCertLookup.cc +++ b/src/iocore/net/SSLCertLookup.cc @@ -33,6 +33,7 @@ #include "P_SSLUtils.h" +#include #include #include #include @@ -237,7 +238,7 @@ SSLCertContext::SSLCertContext(SSLCertContext const &other) userconfig = other.userconfig; keyblock = other.keyblock; ctx_type = other.ctx_type; - std::lock_guard lock(other.ctx_mutex); + ts::bravo::shared_lock lock(other.ctx_mutex); ctx = other.ctx; } @@ -249,7 +250,7 @@ SSLCertContext::operator=(SSLCertContext const &other) this->userconfig = other.userconfig; this->keyblock = other.keyblock; this->ctx_type = other.ctx_type; - std::lock_guard lock(other.ctx_mutex); + ts::bravo::shared_lock lock(other.ctx_mutex); this->ctx = other.ctx; } return *this; @@ -258,14 +259,14 @@ SSLCertContext::operator=(SSLCertContext const &other) shared_SSL_CTX SSLCertContext::getCtx() { - std::lock_guard lock(ctx_mutex); + ts::bravo::shared_lock lock(ctx_mutex); return ctx; } void SSLCertContext::setCtx(shared_SSL_CTX sc) { - std::lock_guard lock(ctx_mutex); + std::lock_guard lock(ctx_mutex); ctx = std::move(sc); } From f7cc3a4cb820eb5054622fa5b9a80e56e94db62a Mon Sep 17 00:00:00 2001 From: Craig Taylor Date: Mon, 20 Apr 2026 10:43:34 -0600 Subject: [PATCH 2/2] Replace BRAVO with std::shared_mutex for SSLCertContext Switch from ts::bravo::shared_mutex to std::shared_mutex. The contention pattern (short bursts, not sustained) doesn't benefit from BRAVO's per-thread slots, and std::shared_mutex avoids the ~16 KB per-mutex memory overhead. --- src/iocore/net/P_SSLCertLookup.h | 6 +++--- src/iocore/net/SSLCertLookup.cc | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/iocore/net/P_SSLCertLookup.h b/src/iocore/net/P_SSLCertLookup.h index 2bf9e57d618..5d13a6300f4 100644 --- a/src/iocore/net/P_SSLCertLookup.h +++ b/src/iocore/net/P_SSLCertLookup.h @@ -26,7 +26,7 @@ #include "iocore/eventsystem/ConfigProcessor.h" #include "iocore/net/SSLTypes.h" #include "records/RecCore.h" -#include "tsutil/Bravo.h" +#include #include #include @@ -94,8 +94,8 @@ using shared_ssl_ticket_key_block = std::shared_ptr; */ struct SSLCertContext { private: - mutable ts::bravo::shared_mutex ctx_mutex; - shared_SSL_CTX ctx; + mutable std::shared_mutex ctx_mutex; + shared_SSL_CTX ctx; public: SSLCertContext() : ctx_mutex(), ctx(nullptr), opt(SSLCertContextOption::OPT_NONE), userconfig(nullptr), keyblock(nullptr) {} diff --git a/src/iocore/net/SSLCertLookup.cc b/src/iocore/net/SSLCertLookup.cc index e13e28e1063..4b51a21579e 100644 --- a/src/iocore/net/SSLCertLookup.cc +++ b/src/iocore/net/SSLCertLookup.cc @@ -238,7 +238,7 @@ SSLCertContext::SSLCertContext(SSLCertContext const &other) userconfig = other.userconfig; keyblock = other.keyblock; ctx_type = other.ctx_type; - ts::bravo::shared_lock lock(other.ctx_mutex); + std::shared_lock lock(other.ctx_mutex); ctx = other.ctx; } @@ -250,7 +250,7 @@ SSLCertContext::operator=(SSLCertContext const &other) this->userconfig = other.userconfig; this->keyblock = other.keyblock; this->ctx_type = other.ctx_type; - ts::bravo::shared_lock lock(other.ctx_mutex); + std::shared_lock lock(other.ctx_mutex); this->ctx = other.ctx; } return *this; @@ -259,7 +259,7 @@ SSLCertContext::operator=(SSLCertContext const &other) shared_SSL_CTX SSLCertContext::getCtx() { - ts::bravo::shared_lock lock(ctx_mutex); + std::shared_lock lock(ctx_mutex); return ctx; }