-
Notifications
You must be signed in to change notification settings - Fork 352
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
Implement asynchronous support in BufferingJsonReader #2264
Implement asynchronous support in BufferingJsonReader #2264
Conversation
bool result = await this.ReadInternalAsync() | ||
.ConfigureAwait(false); | ||
|
||
if (this.asyncInnerReader.NodeType == JsonNodeType.StartObject) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe invert this to have the nesting level reduced.
.ConfigureAwait(false); | ||
if (!readErrorStringPropertyResult.Item1) | ||
{ | ||
return Tuple.Create(false, error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if nullable would be better for these cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marabooy To explain the logic, the only time this method returns the second component of the tuple as null
is before entering this while loop. Within this loop, we return the error
object with as many properties we have read before coming across some unintelligible property. For example, if successfully read code
, message
, target
, and innererror
properties and the come across details
and we're unhappy, we don't return a tuple with false
as first component and null
as second component. Instead, the second component will contain the error
object with the properties we had read successfully populated.
if (this.isBuffering) | ||
{ | ||
Debug.Assert(this.currentBufferedNode != null, "this.currentBufferedNode != null"); | ||
return Task.FromResult(this.currentBufferedNode.Value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, you opted not to use ValueTask in this case because this is a public method or because the synchronous code-path is less frequent than the async one?
196deee
to
19cc4d6
Compare
|
||
if (value == null) | ||
{ | ||
result = new MemoryStream(new byte[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can use Array.Empty<byte>()
to avoid allocating an empty array each time. Consider using it in the sync method as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@habbes Array.Empty<byte>()
is not available in net45 and netstandard1.1. I don't know if it'd be worthwhile to do this:
#if NETSTANDARD2_0
result = new MemoryStream(Array.Empty<byte>());
#else
result = new MemoryStream(new byte[0]);
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gathogojr this is an issue that is causing too many warnings. Will probably fix it in 8.x where we remove support for net45
if (this.bufferedNodesHead == null) | ||
{ | ||
// capture the current state of the reader as the first item in the buffer (if there are none) | ||
object value = await this.asyncInnerReader.GetValueAsync() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a lot of these methods are async because of getting the value. I wonder if we could avoid some of the overhead when the value is immediately available. But that's probably a discussion for another day.
{ | ||
this.AssertAsynchronous(); | ||
|
||
if (!this.isBuffering && this.asyncInnerReader is IJsonStreamReaderAsync asyncStreamReader) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this check for IJsonStreamReaderAsync
in a few different places. I wonder if it makes sense to have a field where this is stored so that the casting only has to happen once. I also wonder if that field should be set in the constructor. I can see there being different use cases where it makes sense to do it on the fly versus doing it in the constructor. Any thoughts?
|
||
object value = await this.GetValueAsync() | ||
.ConfigureAwait(false); | ||
return value is string || value == null || this.NodeType == JsonNodeType.StartArray || this.NodeType == JsonNodeType.StartObject; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the subsequent conditions are predicated on this first one for any reason, so I'm wondering if it makes sense to do the cast last due to short circuit evaluation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@corranrogue9 Does a cast actually happen here given that value
is already boxed and string
is a reference type? In addition, supposing StartArray
and StartObject
occur rarely, do we not end up almost always doing the "cheap" comparisons as well as evaluating value is string
expression?
7217b6c
to
f6e08da
Compare
428f491
to
00f1b67
Compare
00f1b67
to
ec90ede
Compare
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
|
||
if (value == null) | ||
{ | ||
result = new MemoryStream(new byte[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gathogojr this is an issue that is causing too many warnings. Will probably fix it in 8.x where we remove support for net45
Issues
This pull request partially fulfills #2019.
Description
Implement asynchronous support in
BufferingJsonReader
Checklist (Uncheck if it is not completed)
Additional work necessary
If documentation update is needed, please add "Docs Needed" label to the issue and provide details about the required document change in the issue.