-
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
[API Proposal]: Efficient EndPoint serialization #78993
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsBackground and motivationSerializing general We can workaround this by special-casing Instead working around our own inefficient abstractions, we should consider adding an alternative modern and efficient API to serialize arbitrary API Proposalnamespace System.Net;
public abstract class EndPoint
{
// Existing:
// public virtual SocketAddress Serialize();
// public virtual EndPoint Create(SocketAddress socketAddress);
// Returns true if the EndPoint is serializable into a linear native structure
public virtual bool TryGetSocketAddressSize(out int size);
public virtual void Serialize(Span<byte> socketAddress);
public virtual EndPoint Create(ReadOnlySpan<byte> socketAddress);
} API Usageif (endPoint.TryGetSocketAddressSize(out int size))
{
Span<byte> socketAddress = size < 256 ? stackalloc byte[size] : new byte[size];
endPoint.Serialize(socketAddress);
// use socketAddress
} Alternative DesignsI can't think of a significantly different design that would also delegate the buffer lifecycle management to the user. RisksNo response
|
What would the default Create(ROS) implementation be to keep backward compatibility? A call to Create(SocketAddress)? |
Yes, that would be the only way to keep things compatible. |
Seems odd that Create looks like a factory method but it's not static. Maybe add sample API usage that shows how that's used? |
@ericstj it's matching the existing overload. The proposed overload takes The usage is unusual, but it's legacy design: an existing |
Triage: depends on the fate of #30797, moving to future. |
Background and motivation
Serializing general
EndPoint
instances into buffers/structures to be used with low-level interop code requires instantiating aSocketAddress
and copying its bytes to a separate buffer manually. This leads to 2 extra allocations:SocketAddress
and the underlying buffer. This is one of the main reasons our SendTo/ReceiveFrom methods allocate a lot, see discussion in #30797.We can workaround this by special-casing
IPEndPoint
(#78591), but that would introduce complexity to the Socket codebase if implemented across all sync and async variants and doesn't work with arbitrary endpoints. We can also exposeSocketAddress.Buffer
(#78757), but IMO it's a partial solution, since it doesn't help with the allocations.Instead of working around our own inefficient abstractions, we should consider adding an alternative modern and efficient API to serialize arbitrary
EndPoint
-s into user-provided buffers. This would help simplifying and improving socket code while keeping it compatible with arbitrary endpoints.API Proposal
API Usage
Alternative Designs
I can't think of a significantly different design that would also delegate the buffer lifecycle management to the consumer of the API.
If we think that
DnsEndpoint
is the only exception that is not serializable and needs special threatment, we can expose anint Size
property instead ofTryGetSocketAddressSize
.Risks
Considering compatibility, the only correct way to implement
TryGetSocketAddressSize(out int size)
is inefficient and may regress path that uses existing 3rd party endpoints which are not updated with overloads:This is not a concern if we think
DnsEndPoint
is the only special case that is not serializable.The text was updated successfully, but these errors were encountered: