-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Send connection WINDOW_UPDATE before RTT PING #97881
Conversation
Tagging subscribers to this area: @dotnet/ncl Issue DetailsFixes #97131. Some servers in GCP have a non-standard ping accounting mechanism, meaning they reset their unsolicited PING counter when receiving
Ideally, this fix should be backported to all supported versions.
|
if (_pendingWindowUpdate == 0) return false; | ||
LogExceptions(SendWindowUpdateAsync(0, _pendingWindowUpdate)); | ||
_pendingWindowUpdate = 0; | ||
return true; |
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.
ExtendWindow
has unnecessary synchronization around _pendingWindowUpdate
manipulation which is didn't add to this method. See #97878.
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.
This is lite on unit tests. What about tests for scenarios that will and won't trigger a ping? And a test that fails if WINDOWS_UPDATE isn't present.
// When sendWindowUpdateBeforePing is true, try to send a WINDOW_UPDATE to make Google backends happy. | ||
// Unless we are doing the initial burst, do not send PING if we were not able to send the WINDOW_UPDATE. | ||
// See point 3. in the comments above the class definition for more info. | ||
if (sendWindowUpdateBeforePing && !connection.ForceSendConnectionWindowUpdate() && !initial) |
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.
Where are places that can send a windows update? Can a connection be in the situation where a window update is always being sent somewhere else and when it comes time to send a ping, the pending window update is always empty?
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.
Where are places that can send a windows update?
For connection window the standard method is ExtendWindow
the new one introduced in this PR is ForceSendConnectionWindowUpdate
. There are no other places sending WINDOW_UPDATE for the connection.
Can a connection be in the situation where a window update is always being sent somewhere else, the pending window update is always empty?
ExtendWindow
will send a "standard" connection WINDOW_UPDATE only if receiving DATA will make _pendingWindowUpdate
pass ConnectionWindowThreshold
. If that's the case, sendWindowUpdateBeforePing
will be false
at this line, so we won't send a WINDOW_UPDATE in DataOrHeadersReceived
.
Note that receiving DATA triggers ExtendWindow
and DataOrHeadersReceived
sequentially (with the change in the PR WINDOW_UPDATE goes first):
runtime/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs
Lines 772 to 779 in 7064b1f
if (frameData.Length > 0) | |
{ | |
bool windowUpdateSent = ExtendWindow(frameData.Length); | |
if (!endStream) | |
{ | |
_rttEstimator.OnDataOrHeadersReceived(this, sendWindowUpdateBeforePing: !windowUpdateSent); | |
} | |
} |
...libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamWindowManager.cs
Show resolved
Hide resolved
Pushed a test in e93920a. |
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.
LGTM.
I don't fully understand the window & ping management but I don't have any concerns. Hopefully testing was done to ensure correctness.
And I guess excessive updates is the biggest risk of this change, right?
The amount of WINDOW_UPDATE-s we send did not get significantly higher. Now we essentially do the same as the |
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.
LGTM
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
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.
LGTM.
Side question: as far as I understand our current logic, we'll keep sending pings once every ~2 seconds, but only update the RTT if it gets lower.
Are the updates after the initial burst meaningful? That is, we expect the RTT might decrease, but we don't care if it increases?
[Deleted my previous comment because it did not make sense.] Adjusting RTT upwards would risk growing the window "accidentally" in case of an occasional high delay measurement: Lines 108 to 109 in 4928f3c
With an unstable connection the minimum delay is hopefully constant in long run for most practical SocketsHttpHandler use cases, or at least this is the assumption behind the current strategy. |
…med_ResetsStreamAndThrowsOnRequestStreamWriteAndResponseStreamRead...
/azp run runtime-libraries-coreclr outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
CI failures are unrelated, the massive outerloop failures are caused by #96035. |
/backport to release/8.0-staging |
Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/7892640557 |
/backport to release/7.0-staging |
Started backporting to release/7.0-staging: https://github.com/dotnet/runtime/actions/runs/7892642858 |
/backport to release/6.0-staging |
Started backporting to release/6.0-staging: https://github.com/dotnet/runtime/actions/runs/7892646182 |
Fixes #97131.
Some servers in GCP have a non-standard ping accounting mechanism, meaning they reset their unsolicited PING counter when they receive
DATA
,HEADERS
orWINDOW_UPDATE
. To comply with this behavior, this PR adjusts the RTT logic ensuring that a connectionWINDOW_UPDATE
is being sent out before we send an RTTPING
by applying two changes:_pendingWindowUpdate
credits. Do not send a PING if this is not possible (_pendingWindowUpdate == 0
). Just like RTT PINGs, such WINDOW_UPDATEs are relatively rare and should not hurt performance.Ideally, this fix should be backported to all supported versions.