Skip to content
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

SocketAsyncContext should not need to pin Span buffers for sync APIs #46600

Open
geoffkizer opened this issue Jan 5, 2021 · 2 comments
Open
Labels
area-System.Net.Sockets enhancement Product code improvement that does NOT require public API changes/additions tenet-performance Performance related issue
Milestone

Comments

@geoffkizer
Copy link
Contributor

Currently, if you call a sync Span-based Socket overload like Socket.Receive(Span<byte> buffer), and we end up going through the sync-over-async path in SocketAsyncContext, we will end up pinning the buffer when data is not immediately available from the socket.

See references to BufferPtrReceiveOperation and BufferPtrSendOperation in SocketAsyncContext.

In theory, this shouldn't be necessary. All sync operation handling happens on the original calling thread, so we can simply hold on to the Span there. The problem is that the structure of the code currently requires that we store this state on the Operation object, which means we need to pin the Span and treat it as a native pointer.

We should fix this. This would also allow us to remove the duplication of code that currently exists between the byte[] sync overloads and the Span sync overloads.

More generally, we shouldn't really need to store any operation-specific state on the Operation objects for sync operations; it can all live on the calling stack. This would likely simplify the code, and make these operations more efficient since we don't need to allocate an operation each time.

@geoffkizer geoffkizer added this to the Future milestone Jan 5, 2021
@ghost
Copy link

ghost commented Jan 5, 2021

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Currently, if you call a sync Span-based Socket overload like Socket.Receive(Span<byte> buffer), and we end up going through the sync-over-async path in SocketAsyncContext, we will end up pinning the buffer when data is not immediately available from the socket.

See references to BufferPtrReceiveOperation and BufferPtrSendOperation in SocketAsyncContext.

In theory, this shouldn't be necessary. All sync operation handling happens on the original calling thread, so we can simply hold on to the Span there. The problem is that the structure of the code currently requires that we store this state on the Operation object, which means we need to pin the Span and treat it as a native pointer.

We should fix this. This would also allow us to remove the duplication of code that currently exists between the byte[] sync overloads and the Span sync overloads.

More generally, we shouldn't really need to store any operation-specific state on the Operation objects for sync operations; it can all live on the calling stack. This would likely simplify the code, and make these operations more efficient since we don't need to allocate an operation each time.

Author: geoffkizer
Assignees: -
Labels:

area-System.Net.Sockets, tenet-performance

Milestone: Future

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Jan 5, 2021
@antonfirsov
Copy link
Member

We should also find new patterns of code sharing to consolidate sync method duplications in Socket.cs.

For example Receive(byte[] ...), Receive(Span<byte> ...) and Receive(IList<ArraySegment<byte>> ...) are mostly duplicates, and the ReceiveMessageFrom duplication introduced in #46285 is even worse.

@karelz karelz added enhancement Product code improvement that does NOT require public API changes/additions and removed untriaged New issue has not been triaged by the area owner labels Feb 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Net.Sockets enhancement Product code improvement that does NOT require public API changes/additions tenet-performance Performance related issue
Projects
None yet
Development

No branches or pull requests

4 participants