-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Ensure that JSON properties can be skipped without buffering their entire contents. #96856
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
Conversation
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsMakes the following changes:
Fix #96559.
|
@@ -21,6 +21,59 @@ public static ReadOnlySpan<byte> GetSpan(this scoped ref Utf8JsonReader reader) | |||
return reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; | |||
} | |||
|
|||
/// <summary> |
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.
Logic moved essentially unchanged from JsonConverter.ReadAhead.cs
/// </summary> | ||
/// <param name="targetDepth">The target depth we want to eventually skip to.</param> | ||
/// <returns>True if the entire JSON value has been skipped.</returns> | ||
internal bool TrySkipPartial(int targetDepth) |
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.
The existing TrySkipHelper
has been retrofitted to the resumable TrySkipPartial
method, minus the checkpointing semantics.
{ | ||
// For a continuation, read ahead here to avoid having to build and then tear | ||
// down the call stack if there is more than one buffer fetch necessary. | ||
if (!SingleValueReadWithReadAhead(requiresReadAhead: true, ref reader, ref state)) |
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.
Here's the crux of the second change made by this PR: re-entrant serialization operations no longer perform read-ahead of the next value (the converter doesn't require it in this case). We let the JsonSerializerOptions.DefaultBufferSize
be the only guide of how much data we add to the buffer before re-entering deserialization.
if (!isContinuation) | ||
{ | ||
#if DEBUG | ||
// For performance, only perform token type validation of converters on debug builds. | ||
Debug.Assert(state.Current.OriginalTokenType == JsonTokenType.None); | ||
state.Current.OriginalTokenType = reader.TokenType; |
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.
We now need to store this value in all builds to track resumable skip operations.
[Fact] | ||
[SkipOnCoreClr("https://github.com/dotnet/runtime/issues/45464", ~RuntimeConfiguration.Release)] | ||
public async Task ReadSimpleObjectAsync() | ||
[Theory] |
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.
Converted this test suite to use theories because it was causing me grief while debugging.
// Read the key name. | ||
if (!reader.Read()) | ||
{ | ||
value = default; | ||
return false; | ||
} | ||
|
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.
Changing the order of state update operations since we no longer rely on the root method to advance the reader for us on resumed operations.
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.
LGTM. thanks for the comments you added in the PR, it helped me understand the changes.
Makes the following changes:
Fix #96559.