aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/httpsys.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-10-02 12:56:07 +0200
committerGitHub <[email protected]>2023-10-02 12:56:07 +0200
commit82efd6ef7359b281d0cb258ce039d21d8d1549b2 (patch)
tree7879183b6a78421376948640d04e01af83371639 /src/zenhttp/httpsys.cpp
parentHandle OOM and OOD more gracefully to not spam Sentry with error reports (#434) (diff)
downloadzen-82efd6ef7359b281d0cb258ce039d21d8d1549b2.tar.xz
zen-82efd6ef7359b281d0cb258ce039d21d8d1549b2.zip
reduce time spent holding http.sys transaction lock (#437)
* changed where calls to IssueNewRequestMaybe are made to reduce per-transaction lock contention * minor: reduce stack frame for HttpSysTransaction::IoCompletionCallback
Diffstat (limited to 'src/zenhttp/httpsys.cpp')
-rw-r--r--src/zenhttp/httpsys.cpp39
1 files changed, 25 insertions, 14 deletions
diff --git a/src/zenhttp/httpsys.cpp b/src/zenhttp/httpsys.cpp
index 60358d0b0..c7ed0bb2f 100644
--- a/src/zenhttp/httpsys.cpp
+++ b/src/zenhttp/httpsys.cpp
@@ -1111,12 +1111,13 @@ HttpSysServer::Run(bool IsInteractive)
}
void
-HttpSysServer::OnHandlingRequest()
+HttpSysServer::OnHandlingNewRequest()
{
if (--m_PendingRequests > m_MinPendingRequests)
{
// We have more than the minimum number of requests pending, just let someone else
- // enqueue new requests
+ // enqueue new requests. This should be the common case as we check if we need to
+ // enqueue more requests before exiting the completion handler.
return;
}
@@ -1242,6 +1243,16 @@ HttpSysTransaction::IssueInitialRequest(std::error_code& ErrorCode)
thread_local bool t_IsHttpSysThreadNamed = false;
static std::atomic<int> HttpSysThreadIndex = 0;
+static void
+NameCurrentHttpSysThread()
+{
+ t_IsHttpSysThreadNamed = true;
+ const int ThreadIndex = ++HttpSysThreadIndex;
+ zen::ExtendableStringBuilder<16> ThreadName;
+ ThreadName << "httpio_" << ThreadIndex;
+ SetCurrentThreadName(ThreadName);
+}
+
void
HttpSysTransaction::IoCompletionCallback(PTP_CALLBACK_INSTANCE Instance,
PVOID pContext /* HttpSysServer */,
@@ -1250,19 +1261,13 @@ HttpSysTransaction::IoCompletionCallback(PTP_CALLBACK_INSTANCE Instance,
ULONG_PTR NumberOfBytesTransferred,
PTP_IO Io)
{
- UNREFERENCED_PARAMETER(Io);
- UNREFERENCED_PARAMETER(Instance);
- UNREFERENCED_PARAMETER(pContext);
+ ZEN_UNUSED(Io, Instance);
// Assign names to threads for context
if (!t_IsHttpSysThreadNamed)
{
- t_IsHttpSysThreadNamed = true;
- const int ThreadIndex = ++HttpSysThreadIndex;
- zen::ExtendableStringBuilder<128> ThreadName;
- ThreadName << "httpio_" << ThreadIndex;
- SetCurrentThreadName(ThreadName);
+ NameCurrentHttpSysThread();
}
// Note that for a given transaction we may be in this completion function on more
@@ -1275,6 +1280,15 @@ HttpSysTransaction::IoCompletionCallback(PTP_CALLBACK_INSTANCE Instance,
{
delete Transaction;
}
+
+ // Ensure new requests are enqueued as necessary. We do this here instead
+ // of inside the transaction completion handler now to avoid spending time
+ // in unrelated API calls while holding the transaction lock
+
+ if (HttpSysServer* HttpServer = reinterpret_cast<HttpSysServer*>(pContext))
+ {
+ HttpServer->IssueNewRequestMaybe();
+ }
}
bool
@@ -1336,7 +1350,7 @@ HttpSysTransaction::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTran
if ((CurrentHandler == &m_InitialHttpHandler) && m_InitialHttpHandler.IsInitialRequest())
{
// Ensure we have a sufficient number of pending requests outstanding
- m_HttpServer.OnHandlingRequest();
+ m_HttpServer.OnHandlingNewRequest();
}
auto NewCompletionHandler = CurrentHandler->HandleCompletion(IoResult, NumberOfBytesTransferred);
@@ -1344,9 +1358,6 @@ HttpSysTransaction::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTran
IsRequestPending = IssueNextRequest(NewCompletionHandler);
}
- // Ensure new requests are enqueued as necessary
- m_HttpServer.IssueNewRequestMaybe();
-
if (IsRequestPending)
{
// There is another request pending on this transaction, so it needs to remain valid