Skip to content

Stream copy default buffer size causes allocation to go to LOH. #43179

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
ManickaP opened this issue Oct 8, 2020 · 5 comments
Closed

Stream copy default buffer size causes allocation to go to LOH. #43179

ManickaP opened this issue Oct 8, 2020 · 5 comments

Comments

@ManickaP
Copy link
Member

ManickaP commented Oct 8, 2020

The constant was picked up to prevent allocation in LOH:

// We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
// The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
// improvement in Copy performance.
private const int DefaultCopyBufferSize = 81920;

Then we refactored Stream.CopyTo* to use ArrayPool (commit from Oct 2016) which rents buffers in nearest, big enough, 2^n size:

// Buffers are bucketed so that a request between 2^(n-1) + 1 and 2^n is given a buffer of 2^n
// Bucket index is log2(bufferSize - 1) with the exception that buffers between 1 and 16 bytes
// are combined, and the index is slid down by 3 to compensate.
// Zero is a valid bufferSize, and it is assigned the highest bucket index so that zero-length
// buffers are not retained by the pool. The pool will return the Array.Empty singleton for these.
return BitOperations.Log2((uint)bufferSize - 1 | 15) - 3;

This will lead to renting a buffer with the size of 131 072, falling over the LOH threshold.

I believe this side-effect was unintentional. The question is whether it's worth fixing since the buffer gets reused?

Discovered while investigating: dotnet/yarp#151

cc: @stephentoub

@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Oct 8, 2020
@stephentoub
Copy link
Member

stephentoub commented Oct 8, 2020

Thanks, yeah, this was discussed here:
#37693 (comment)
After that I experimented with changing it, but decreasing the buffer size makes a measurable impact on throughout in some cases, and the buffer ends up getting pooled a lot of the time, so it wasn't clear that decreasing it was actually the right call.

@ManickaP
Copy link
Member Author

ManickaP commented Oct 8, 2020

I see, thanks for linking it.
We should at least get rid of the misleading comment above the DefaultCopyBufferSize.

I'm not sure if it's worth updating the constant to 128kB to reflect the actual size it gets from the ArrayPool. I guess the ArrayPool might change in the future and we could end up with even bigger unintentional allocations.

@carlossanlop carlossanlop removed the untriaged New issue has not been triaged by the area owner label Oct 9, 2020
@jozkee jozkee added this to the Future milestone Oct 9, 2020
Copy link
Contributor

Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

This process is part of our issue cleanup automation.

@dotnet-policy-service dotnet-policy-service bot added backlog-cleanup-candidate An inactive issue that has been marked for automated closure. no-recent-activity labels Apr 11, 2025
Copy link
Contributor

This issue will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.

@dotnet-policy-service dotnet-policy-service bot removed this from the Future milestone Apr 25, 2025
@github-actions github-actions bot locked and limited conversation to collaborators May 25, 2025
@dotnet-policy-service dotnet-policy-service bot removed no-recent-activity backlog-cleanup-candidate An inactive issue that has been marked for automated closure. labels May 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants