-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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]: Enable reusing System.Net.Http.Headers.*HeaderValue instances to improve efficiency. #83543
Comments
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. |
Tagging subscribers to this area: @dotnet/ncl Issue DetailsBackground and motivationThe various *HeaderValue types defined in System.Net.Http.Headers provide essential functionality to parse incoming headers reliably. Unfortunately, these types are one-shot only, meaning that new instances of the types need to be allocated for every header being parsed for all incoming requests. This leads to garbage and extra collections, slowing down the overall throughput of the service. API ProposalI recommend extending the System.Net.Http.Headers types in two ways:
So taking CacheControlHeaderValue as an example:
API Usagevar cchv = new CacheControlHeaderValue();
if (cchv.TryParse(hdr1))
{
// do something with cchv
}
if (cchv.TryParse(hdr2))
{
// do something with cchv
} Alternative DesignsNo response RisksNo response
|
Do you happen to have any real-world data from a service showing how many of each header type you're seeing? Taking Caching these may quickly become more expensive than just allocating them. Nit re: using |
This is peanut butter cost. 100 bytes here and there doesn't seem like much, but if you're processing a few thousand requests per second the costs mount. Yes, all embedded collections can be reused, eliminating the incremental cost of resizing. Regarding the suggestion to use spans rather than strings, this is driven by another objective which I have is to introduce support at the lower level for not materializing strings for the header values in the first place. Instead, the application layer can be handed fully-parsed state, considerably reducing per-request allocation burden. So this proposal would tackle a chunk of the problem and would put its API inline with many other parsing APIs which have been upgraded to spans throughout the framework. |
#83640 should help with allocations here somewhat.
Do you have any ideas for how something like that could be done with HttpClient? I think it would be better to decide whether exposing raw Span-based access to header values is possible and beneficial with HttpClient given the constraints of existing APIs before we add If the service is okay with caching value objects and dealing with raw value buffers, would it make more sense to skip the value object allocation entirely? Taking public class ViaHeaderValue
{
public string? ProtocolName { get; }
public string ProtocolVersion { get; }
public string ReceivedBy { get; }
public string? Comment { get; } While you could cache and save the allocation of the public static bool TryParse(
ReadOnlySpan<char> value,
out Range? protocolName,
out Range protocolVersion,
out Range receivedBy,
out Range? comment); |
@MihaZupan I think I'd go with a half-way solution. Return a struct to get a good type to use, but replace strings with Range objects. So something like: public class ViaHeaderValue : IResettable
{
public bool TryReset();
public bool TryParse(ReadOnlySpan<char> input);
public Range ProtocolName { get; }
public Range ProtocolVersion { get; }
public Range ReceivedBy { get; }
public Range Comment { get; }
} |
Triage: this is a nice-to-have for perf. We would need to understand the scenarios where the API would be consumed to reach agreement on the API shape, so we would be reaching out offline @geeknoid |
Background and motivation
The various *HeaderValue types defined in System.Net.Http.Headers provide essential functionality to parse incoming headers reliably. Unfortunately, these types are one-shot only, meaning that new instances of the types need to be allocated for every header being parsed for all incoming requests. This leads to garbage and extra collections, slowing down the overall throughput of the service.
API Proposal
I recommend extending the System.Net.Http.Headers types in two ways:
So taking CacheControlHeaderValue as an example:
API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: