-
Notifications
You must be signed in to change notification settings - Fork 193
Expose Content-Length in IHttpResponseFeature #407
Comments
Is the cost you're measuring for long -> string -> ascii bytes, and you're trying to shorten it to long -> ascii bytes? Background: System.Web has had no end of problems special casing certain headers to bypass the header collection. Response cookies are a particularly bad example where it keeps a separate collection for them and only adds them to the headers at the end of the response. This causes conflicts for anyone using the headers directly. We don't want to repeat this mistake so we've kept the headers collection as the source of truth for all headers. |
Trying to shorten it to long -> pre allocated byte buffer; so zero alloc. Am ok with the other headers, as they come with a user generated cost, and where the user has already created the string; but this is generally always present except if chunked and is a hidden library cost that cannot be worked around. |
For comparison its 30% of the alloc cost of DI: aspnet/DependencyInjection#291 |
StaticFiles does set it but most of our other components don't, they rely on the server to chunk or to buffer and set it for them. In those cases the server can take shortcuts internally. I can't think of any of our other libraries that set it by default. |
MVC does in some extremely obscure scenarios, but not anything @benaadams or the average user is likely to have encountered. |
With the current set up this is ok:
But using the strongly typed
Which feels a bit wrong. This is because it goes ContentLength->new HeaderDictionary->ParsingHelpers.SetContentLength->value.ToString()->IDictionary[key]= If Also the servers response.write can't assume the result is complete until the invoked closure is complete. |
The content length being set has to appear in the headers dictionary. It could be lazy be we want a single source of truth. Managing separate ways to set data is a PITA (we know from experience) |
There are already 2 ways; strongly typed on Request route and weakly typed via headers. They both resolve to headers. You could change this so setting via headers goes to For output it would follow a similar path to StatusCode and ReasonPhrase? |
Also it means when deciding to chunk the check is: ContentLength.HasValue vs HeadersDictionary.Contains("Content-Length")+ignore-case |
Content-Length can only be a numeric >= 0 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13 but you can set it to a whole bunch of weird via the headers, including multiple values; which if you try to read back via ContentLength will just say its not set I think that's all I've got; will leave this bone alone now :) |
To resolve this issue you'd need to convert it from the header back to a long aspnet/KestrelHttpServer#175 Though kestrel does do the work of re-parsing from the header back to an int perhaps for this reason: https://github.com/aspnet/KestrelHttpServer/blob/c50aec17292b9f6d444da5f11637fd3c9146146d/src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs#L54 |
Moving this to Backlog as we will be in RC2 ask mode very soon. If you feel strongly about this issue, please ping me. |
I feel strongly about it; but am ok with it being a post RTM discussion (although it would be a breaking change) |
To clarify: Is breaking change for servers, not for end users as the attribute is already exposed - its just how its implemented that's emulated. |
Did some measurements; the difference between these two lines response.ContentLength = 13; response.Headers["Content-Length"] = "13"; Is as follows
|
Benchmarks aspnet/KestrelHttpServer#1256 |
2.0 Proposal: Are there any other headers that would benefit from direct IHeaderDictionary properties? |
The Date header? |
Any you'd want to though? People wouldn't normally read the date request header, and shouldn't be encouraged to write the date response header 😉 |
Thank you for resolving this 😁 |
At the moment accessing content-length goes to string and back through parsing and the header collection. It is a
long?
on Response.The string transitions are alloc heavy for 2000 requests at 108k meaning 54 Meg per 1M requests:
What I'd much prefer is to have the
long?
directly so I can output that straight to bytes without going via string or allocating.The text was updated successfully, but these errors were encountered: