-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Using Interlocked in InputFlowControl and Http2Stream #57968
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
Conversation
src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/InputFlowControl.cs
Show resolved
Hide 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.
I have to admit I'm curious whether this has any effect on a real benchmark.
| Available -= bytes; | ||
| } | ||
|
|
||
| // bytes can be negative when SETTINGS_INITIAL_WINDOW_SIZE decreases mid-connection. |
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.
If I'm reading this comment correctly, allowing it to go negative is important. How can it be a uint now?
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.
Now I thought this is wrong, but actually it works because: https://sharplab.io/#v2:EYLgtghglgdgNAFxAJwK4wD4AEBMBGAWAChjYEACCcgXnIGYAGAbmIgFpqAWZ4rPATgAUgsgEpBAGwD2MAObjUYiKKZA
I am looking into making it more explicit.
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 updated the code and added tests to cover this use-case.
src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/InputFlowControl.cs
Show resolved
Hide resolved
src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/InputFlowControl.cs
Outdated
Show resolved
Hide resolved
src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/InputFlowControl.cs
Outdated
Show resolved
Hide resolved
| FlowControlState currentFlow, computedFlow; | ||
| do | ||
| { | ||
| currentFlow = _flow; // Copy |
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 doesn't need to be a volatile read or something?
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 have based the implementation on the documentation: https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked.compareexchange?view=net-8.0 (see the examples)
I know there is another implementation, which honestly 'reads' safer to me, happy to update if that is preferred:
do
{
startValue = currentValue;
desiredValue = f(startVal);
currentValue = Interlocked.CompareExchange(ref target, desiredValue, startValue);
}
while (startValue != currentValue);
src/Servers/Kestrel/Core/src/Internal/Http2/FlowControl/InputFlowControl.cs
Outdated
Show resolved
Hide resolved
| _pendingUpdateSize = potentialUpdateSize; | ||
| computedPendingUpdateSize = potentialUpdateSize; | ||
| } | ||
| } while (currentPendingSize != Interlocked.CompareExchange(ref _pendingUpdateSize, computedPendingUpdateSize, currentPendingSize)); |
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.
In the locking version, the same thread that updated _flow updated _pendingUpdateSize; now it seems like different threads could update them. It's not obvious to me whether that matters.
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.
As far as I can tell it does not, but I am not sure if I missed any use-case.
|
This seems to have been @halter73's proposal |
c4580f7 to
0c39914
Compare
0c39914 to
5c71428
Compare
|
@JamesNK can you please review this? Thanks! |
|
I think @halter73 was going to review this one, since it was his suggestion. |
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.
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
|
Closing this for now due to inactivity. |
Using Interlocked in InputFlowControl and Http2Stream
Based on the comments of #57236 implementing interlocked in InputFlowControl.
Description
In
InputFlowControlclass the state is encoded byFlowControlState. It uses a singlelongvalue that can beInterlocked.CompareExchanged.The operations of the previous
FlowControltype are now implemented byInputFlowControltype itself.There are two types of performance tests I executed. One in part of the PR as a standard BDN tests, and one type using the following
Testerclass, which is based on the previous discussions of this PR.In the results below:
Interlocked.lock.TryUpdateWindow) was 'just' enough to not to run into this state but on different CPU adjusting these values might be necessary.Testerclass the higher the counter number, the more operations were performed.Executing the benchmarks with BDN (part of the PR):
BEFORE:
AFTER:
Fixes #56794