* Short-circuit SerializeGroupedNodes on no child nodes.
Avoids creating unused Dictionary.
* Don't create Dictionary in ReadAttributeElements if it'll be empty.
* Reduce calls to JsonReader.TokenType virtual property.
* Remove duplicate finished boolean.
Different reasons for finishing the ReadAttributeElements loop are
noted, but the difference isn't acted on, so merge them.
* Check correct XML is from correct TokenType immediately.
(This changes the exception message in the case of it also being an
invalid objectType, but not the exception type).
Between discussion at #1137 and a few rounds of revision at #1159 we
arrived at an optimisation where tasks that are both heavily hit and
very likely to return in a completed state are checked for a status of
either RanToCompletion, Canceled or Faulted and a path is taken where
no await is needed for any of those.
The Canceled and Faulted tasks are returned immediately, allowing that
state to be passed to the caller.
However, these are exceptional cases, and if we just continued the
subsequent await would raise the appropriate exception. Checking for
all three cases instead of just RanToCompletion is optimising for those
execptional conditions at cost (in the form of a larger comparison
segment of code) to the more common cases of the task either being
completed or still running.
Simplify this back to a check just for RanToCompletion.
Make the test for a type being S.D.L.Binary a single test as Binary is
a sealed class and therefore there's no need to test bases.
Make the stored ReflectionObject static, reducing size and repeated
allocations if BinaryConverter is explicitly created by the user.
MoveToContentAsync is often called in states where it will immediately
return true without any reading. In this case return AsyncUtils.True
avoiding allocation or async state-machine.
DoReadAsync is a very heavily hit method, and can often be fulfilled
without creating another state machine, so do this.
The remaining looping async case is the only use of ParsePostValueAsync,
so inline it into the calling method, so there is one less task
allocation.
Return value of EatWhitespaceAsync is never used, returning void reduces
the number of locals an hence the size of the state-machine. Do the same
for EatWhitespace though the impact is less.
Skip attempting write when string is empty.
FirstCharToEscape was introduced for the async version and gives a
faster means to identify the first block before any escaping, so may as
well use it here too.
Conversely, WriteEscapedStringThroughBuffer was introduced to share
code between the sync and async versions, but later optimisations meant
it was no longer used by the async. Inline the code back again.
Create an easily-inlinable method that accesses the array used
by Enumerable.Empty (and hence not just shared within this project
but likely with the client assembly or other libraries it uses)
and use it anywhere a zero-element array is used, reducing allocations.
* Remove unnecessary ToArray call.
* Remove Value property.
One use compares with null, so cast to T is a waste.
This leaves just one other use, so it can be inlined.
* Remove _dontFallbackFirst
Is always true. Remove it and branches for it being false.
* Don't use Expression.Convert to reference types to object.
The end-result is a no-op, so don't waste the allocation.
If Operator is Exists or leftResults is empty don't obtain rightResults,
as not relevant.
Otherwise if rightResults is not an ICollection<JToken> load it into an
List so it won't be recomputed on each enumeration of leftResults.