Skip to content

Commit

Permalink
Avoid string allocation and improve performance of `JsonProperty.Writ…
Browse files Browse the repository at this point in the history
…eTo` (dotnet#90074)

* Avoid string allocation in WriteTo when possible.

System.Text.Json.JsonProperty.WriteTo uses get_Name, calling
JsonElement.GetPropertyName() which would allocate a string.

Use ReadOnlySpan<byte> from the underlying UTF8 json, when possible,
by adding helper methods into JsonDocument & JsonElement.

Fix dotnet#88767

* Avoid alloc in unescaping & escaping.

Current code unescapes & escapes property names and uses ToArray.
Avoid alloc by adding internal GetRaw/WriteRaw methods.

* Fix bugs on escaped property names

Original code doesn't handle GetRaw/WriteRaw on escaped
property names correctly.

* Change IndexOf to Contains if possible.

* Further avoid alloc by inlining GetUnescapedSpan

Allocations are further avoided when the property name is shorter than
JsonConstants.StackallocByteThreshold, by inlining
JsonReaderHelper.GetUnescapedSpan.

* Move writing logic to JsonElement;
Shorten names of new methods;
Add a test of writing out special names.

* Move logic into JsonDocument

* fix format

* fix format 2

* improve comment

* removed unused stub

* added assertion

* removed unnecessary test
  • Loading branch information
karakasa authored Sep 22, 2023
1 parent d563d0e commit 45fe624
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,15 @@ private static void ClearAndReturn(ArraySegment<byte> rented)
}
}

internal void WritePropertyName(int index, Utf8JsonWriter writer)
{
CheckNotDisposed();

DbRow row = _parsedData.Get(index - DbRow.Size);
Debug.Assert(row.TokenType == JsonTokenType.PropertyName);
WritePropertyName(row, writer);
}

private void WritePropertyName(in DbRow row, Utf8JsonWriter writer)
{
ArraySegment<byte> rented = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,13 @@ public void WriteTo(Utf8JsonWriter writer)
_parent.WriteElementTo(_idx, writer);
}

internal void WritePropertyNameTo(Utf8JsonWriter writer)
{
CheckValidInstance();

_parent.WritePropertyName(_idx, writer);
}

/// <summary>
/// Get an enumerator to enumerate the values in the JSON array represented by this JsonElement.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,15 @@ public void WriteTo(Utf8JsonWriter writer)
ThrowHelper.ThrowArgumentNullException(nameof(writer));
}

writer.WritePropertyName(Name);
if (_name is null)
{
Value.WritePropertyNameTo(writer);
}
else
{
writer.WritePropertyName(_name);
}

Value.WriteTo(writer);
}

Expand Down

0 comments on commit 45fe624

Please sign in to comment.