Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Proposal: Form parsing improvements #413

Closed
wants to merge 8 commits into from

Conversation

benaadams
Copy link
Contributor

Cached task pattern for avoiding state machine and task allocation for repeated ReadFormAsync
struct KeyValueAccumulator
Delayed allocations; reduced allocs for empty paths

@dnfclas
Copy link

dnfclas commented Sep 22, 2015

Hi @benaadams, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution!
You've already signed the contribution license agreement. Thanks!

The agreement was validated by .NET Foundation and real humans are currently evaluating your PR.

TTYL, DNFBOT;

public static readonly IReadableStringCollection Empty = new ReadableStringCollection();

private static readonly string[] EmptyKeys = new string[0];
private static readonly IEnumerable<KeyValuePair<string, StringValues>> EmptyEnumerable = (IEnumerable<KeyValuePair<string, StringValues>>)(new KeyValuePair<string, StringValues>[0]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enumerable.Empty<T>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure where that is? Can't seem to grab a ref.

Can do the #if !DNXCORE50 stuff on EmptyKeys with Array.Empty<string>() though?
Also #if DNXCORE50 for EmptyEnumerable = Array.Empty<KeyValuePair<string, StringValues>>())

Didn't know if it was too messy

@@ -119,7 +144,7 @@ public IFormCollection ReadForm()
var section = await multipartReader.ReadNextSectionAsync(cancellationToken);
while (section != null)
{
var headers = new HeaderDictionary(section.Headers);
var headers = section.Headers;
ContentDispositionHeaderValue contentDisposition;
ContentDispositionHeaderValue.TryParse(headers[HeaderNames.ContentDisposition], out contentDisposition);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regression: this will throw if Content-Disposition is missing. You could just use section.ContentDisposition instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which would wrap; so delay wrapping down a few lines for FormFile wouldn't help. Will revert.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed as suggested

@Tratcher
Copy link
Member

Can you share your metrics for these changes?

@benaadams
Copy link
Contributor Author

Can you share your metrics for these changes?

Can't actually run it atm; the dnx unstable feeds are a few versions back so need to wait for them to be updated

@benaadams
Copy link
Contributor Author

Resolves #368 ?

benaadams added a commit to benaadams/HttpAbstractions that referenced this pull request Sep 25, 2015
@benaadams benaadams changed the title Form parsing improvements Proposal: Form parsing improvements Sep 27, 2015

// Some of these code paths use StreamReader which does not support cancellation tokens.
using (cancellationToken.Register(_request.HttpContext.Abort))
using (cancellationToken.Register((Action)_request.HttpContext.Abort))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you casting here? You can actually avoid the delegate allocation per request here as well.

cancellationToken.Register(state => ((HttpContext)state).Abort(), _request.HttpContext)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't work out how to avoid alloc; that will do nicely :)

get { return _form; }
set
{
_parsedFormTask = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not set the cached task here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've got the non-async method; so didn't want to set the task if that's the only path used

@benaadams
Copy link
Contributor Author

Will be covered by rebased #411

@benaadams benaadams closed this Oct 16, 2015
@benaadams benaadams deleted the form-parsing branch May 10, 2016 11:28
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants