Skip to content

StringValues Add IsNull, always set single item to _value#323

Merged
halter73 merged 6 commits into
dotnet:devfrom
benaadams:isnull
Mar 20, 2018
Merged

StringValues Add IsNull, always set single item to _value#323
halter73 merged 6 commits into
dotnet:devfrom
benaadams:isnull

Conversation

@benaadams
Copy link
Copy Markdown
Member

No description provided.

@davidfowl
Copy link
Copy Markdown
Member

@benaadams did you have to reformat all of the methods 🤣

@benaadams
Copy link
Copy Markdown
Member Author

did you have to reformat all of the methods 🤣

Better? 😄

@benaadams
Copy link
Copy Markdown
Member Author

Then can use .IsNull in Kestrel rather than .Count == 0 for less branchy fasterness

@davidfowl
Copy link
Copy Markdown
Member

/cc @Tratcher @halter73

@davidfowl
Copy link
Copy Markdown
Member

Any perf results?

@benaadams
Copy link
Copy Markdown
Member Author

benaadams commented Mar 16, 2018

Any perf results?

This PR is from your point in aspnet/KestrelHttpServer#2347 (comment)

So the perf would be from a follow on change in Kestrel changing header existence checks from the equivalent of

if ((_value != null ? 1 : (_values?.Length ?? 0)) > 0)

to

if (!(_value == null && _values == null))

{
_value = null;
_values = values;
if (values == null || values.Length == 0)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe add a comment explaining that if _values isn't set to null when values.Length is zero, the IsNull property will be broken.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added

@benaadams
Copy link
Copy Markdown
Member Author

CI was slow...

@benaadams
Copy link
Copy Markdown
Member Author

Added change to remove nulls from arrays to cover the corner case of nulls getting in via string[]

This also means the if (value != null) check per item per header on output in Kestrel could be dropped

}
else
{
// Remove any nulls from the array else counts will be off
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is beyond StringValues' purview to modify the input like this. And as far as we know this is a rare corner case so why put the extra effort into it? It's not even worth writing the tests for. None of your other changes in this PR depend on this filter, correct?

Copy link
Copy Markdown
Member Author

@benaadams benaadams Mar 19, 2018

Choose a reason for hiding this comment

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

Its an edge case with consequences.

The string[] ctor is the only way null can appear with a count

new StringValues(new []{(string)null, (string)null, (string)null })

Will report .Count == 3

However, it will also output zero headers; so is it really 3 headers?

As null can get into StringValues values every header value has to be null checked in Kestrel to see if it is null or not before outputting it.

This commit 6a5e5f1 means the previous will report .Count == 0 and all the null checks can be removed from Kestrel for header output.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Common case is there aren't nulls and the string[] ctor is not used; so its pushing to cost for potential null values coming from that .ctor into the .ctor; rather than having guards spread everywhere.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The constructor is called from an implicit converter, it shouldn't be doing non-trivial transformations. StringValues also only wraps the array so you can't prevent those values from becoming null after the constructor.

Since Kestrel needs the values to not be null then it should do a one time filter, possibly via a helper method provided by StringValues like WithoutNulls or GetNonNulls.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Since Kestrel needs the values to not be null then it should do a one time filter, possibly via a helper method provided by StringValues like WithoutNulls or GetNonNulls.

That wouldn't achieve any real benefit over what exists now (and likely would be more expensive)

Reverted

@halter73
Copy link
Copy Markdown
Member

Still LGTM

}

if (obj is string)
if (obj is string st)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: str

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed

@halter73 halter73 merged commit 2fa1ce5 into dotnet:dev Mar 20, 2018
@halter73
Copy link
Copy Markdown
Member

Whoops. I didn't squash this. Sorry about the git history.

@Tratcher
Copy link
Copy Markdown
Member

FYI: This change regressed StringValues.Empty. It used to be equivalent to new string[0], but now it's null. It causes the same problem for MVC's ValueProviderResult.None. @rynowak
https://github.com/aspnet/Mvc/blob/1aeaf69f87cbf91f4f56183eb1254f69a50b406a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ValueProviderResult.cs#L35

@Tratcher
Copy link
Copy Markdown
Member

@benaadams heads up. We're going to revert this and reintroduce it more cautiously by doing full universe builds before merging.

@benaadams
Copy link
Copy Markdown
Member Author

We're going to revert this and reintroduce it more cautiously by doing full universe builds before merging.

Makes sense, a broken build is no place to be...

Tratcher added a commit that referenced this pull request Mar 21, 2018
This reverts commit 2fa1ce5, reversing
changes made to 75b76eb.
@Tratcher
Copy link
Copy Markdown
Member

Reverted. 43ad60b

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