Skip to content

If not waiting for data, allocate memory before checking anything #22225

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

Closed
wants to merge 5 commits into from

Conversation

benaadams
Copy link
Member

To reduce contention between reader and writer on the MemoryPool (as no-delay in the no wait scenario) seen in dotnet/runtime#36956 (comment)

Its a race to see if it can get it before the Flush is picked up; but the Flush invalidatees outstanding Memory, so we can't do it before the Flush :-/

{
// If not waiting for data allocate another buffer immediately after flushing,
// to try and aquire some before the reader takes the lock.
buffer = input.GetMemory(MinAllocBufferSize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the flushTask should always be completed in the benchmark we're looking at, why do you expect calling GetMemory() here instead of the top of the loop to be substantially different? Is it so expensive to retrieve the FlushResult and check few more bools that it's likely to change the timing of GetMemory() relative to another thread waking up?

Copy link
Member Author

@benaadams benaadams May 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mention in dotnet/runtime#36992 (comment) that its basically running a data race; in combination with PR dotnet/runtime#36992 it just needs to set the IsWritingActive flag near the start of GetMemory() before the Reader takes the lock to avoid the lock contention.

I'm not sure it will work and if not then PipeWriter would need a FlushAsync(bool moreData = false) overload; where it doesn't switch out of writing when moreData is true, akin to the linux send(2) flag MSG_MORE, the Windows RioSend RIO_MSG_DEFER flag; or WSASend MSG_PARTIAL flag; which would allow it to either keep using the existing buffer or request a replacement larger one without having the data race.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FlushAsync(bool moreData = false) would be better as Memory.Slice is cheaper than GetMemory() 😉

@@ -209,7 +216,18 @@ private async Task ProcessReceives()

input.Advance(bytesReceived);

var flushTask = input.FlushAsync();
var flushTask = input.FlushAsync(isMoreData: !_waitForData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benaadams @davidfowl Any chance we're getting the isMoreData: API in .NET 5?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; too soon

{
if (buffer.Length - bytesReceived >= MinAllocBufferSize)
{
buffer = buffer.Slice(bytesReceived);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The skipping of the call to GetMemory() doesn't even look like it should be allowed by the PipeWriter. Is this critical for perf?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its what the api would allow

@halter73
Copy link
Member

@benaadams I'm closing this dotnet/runtime#37472 has also been closed. Hopefully we can optimize this more in .NET 6.

@halter73 halter73 closed this Aug 28, 2020
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Jun 6, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Dec 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants