-
Notifications
You must be signed in to change notification settings - Fork 4.9k
[release/2.2] Change HttpConnectionPool.GetConnectionAsync to do read-ahead outside of lock (#) #32568
Conversation
… of lock (dotnet#32495) Minimize the work done inside the lock in order to reduce contention. This means we need to reacquire the lock if the connection isn't usable, but in the fast path case where the connection is usable, we remove the syscalls from being performed while holding the lock.
DescriptionSocketsHttpHandler pools connections, and when it takes a connection from the pool, it checks to see whether the connection is still alive. That check is currently happening while a lock is held, which under heavy load and many short requests can result increased contention on the lock. This change moves that check to outside of the lock, so that in the fast path / common case, the lock is held for a very short period of time. Customer ImpactFor microservices where many ASP.NET requests in turn make many HttpClient calls to other services, the contention can result in significantly reduced throughput than is otherwise possible. The benchmark results shown in #32495 (comment) highlight this impact. Regression?No RiskThis code path is critical to SocketsHttpHandler, used in the processing of all requests, so a mistake here could be impactful. But the change itself is minimal: it moves some checks from inside the lock to outside the lock. The net result is that for the common case, we still take the lock once, but we hold it for a much shorter period of time. In the less common case where we were able to grab a connection but then discover after releasing the lock and doing these checks that the connection is no longer valid (e.g. the server closed it after a timeout), we end up needing to loop around and take the lock again, for a small increase in cost on the uncommon path. |
Eilon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I approve for 2.2, though I don't know the code.
|
The Windows failure is an unrelated pipelines test: ReadAsyncCompletesIfFlushAsyncCanceledMidFlush. @dotnet-bot test Outerloop Windows x64 Debug Build please |
|
cc: @geoffkizer |
|
Approved for 2.2. |
|
The Outerloop Windows failures are unrelated:
|
|
@stephentoub you can hit merge when CI is green (or effectively so) |
|
Thanks |
Port #32495 to release/2.2.
Minimize the work done inside the lock in order to reduce contention. This means we need to reacquire the lock if the connection isn't usable, but in the fast path case where the connection is usable, we remove the syscalls from being performed while holding the lock.
Related to https://github.com/dotnet/corefx/issues/31799