Skip to content
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

Use Utf8JsonWriterCache in JsonNode.To{Json}String #92358

Merged
merged 1 commit into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;

namespace System.Text.Json.Nodes
{
public abstract partial class JsonNode
Expand All @@ -12,8 +14,25 @@ public abstract partial class JsonNode
/// <returns>JSON representation of current instance.</returns>
public string ToJsonString(JsonSerializerOptions? options = null)
{
using PooledByteBufferWriter output = WriteToPooledBuffer(options, options?.GetWriterOptions() ?? default);
return JsonHelpers.Utf8GetString(output.WrittenMemory.Span);
JsonWriterOptions writerOptions = default;
int defaultBufferSize = JsonSerializerOptions.BufferSizeDefault;
if (options is not null)
{
writerOptions = options.GetWriterOptions();
defaultBufferSize = options.DefaultBufferSize;
}

Utf8JsonWriter writer = Utf8JsonWriterCache.RentWriterAndBuffer(writerOptions, defaultBufferSize, out PooledByteBufferWriter output);
try
{
WriteTo(writer, options);
writer.Flush();
return JsonHelpers.Utf8GetString(output.WrittenMemory.Span);
}
finally
{
Utf8JsonWriterCache.ReturnWriterAndBuffer(writer, output);
}
}

/// <summary>
Expand All @@ -37,8 +56,17 @@ public override string ToString()
}
}

using PooledByteBufferWriter output = WriteToPooledBuffer(writerOptions: new JsonWriterOptions { Indented = true });
return JsonHelpers.Utf8GetString(output.WrittenMemory.Span);
Utf8JsonWriter writer = Utf8JsonWriterCache.RentWriterAndBuffer(new JsonWriterOptions { Indented = true }, JsonSerializerOptions.BufferSizeDefault, out PooledByteBufferWriter output);
try
{
WriteTo(writer);
writer.Flush();
return JsonHelpers.Utf8GetString(output.WrittenMemory.Span);
}
finally
{
Utf8JsonWriterCache.ReturnWriterAndBuffer(writer, output);
}
}

/// <summary>
Expand All @@ -50,19 +78,5 @@ public override string ToString()
/// </exception>
/// <param name="options">Options to control the serialization behavior.</param>
public abstract void WriteTo(Utf8JsonWriter writer, JsonSerializerOptions? options = null);

/// <summary>
/// Creates a pooled buffer writer instance and serializes all contents to it.
/// </summary>
internal PooledByteBufferWriter WriteToPooledBuffer(
JsonSerializerOptions? options = null,
JsonWriterOptions writerOptions = default,
int bufferSize = JsonSerializerOptions.BufferSizeDefault)
{
var bufferWriter = new PooledByteBufferWriter(bufferSize);
using var writer = new Utf8JsonWriter(bufferWriter, writerOptions);
WriteTo(writer, options);
return bufferWriter;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,17 @@ internal sealed override JsonValueKind GetValueKindCore()
return element.ValueKind;
}

using PooledByteBufferWriter output = WriteToPooledBuffer();
return JsonElement.ParseValue(output.WrittenMemory.Span, options: default).ValueKind;
Utf8JsonWriter writer = Utf8JsonWriterCache.RentWriterAndBuffer(default, JsonSerializerOptions.BufferSizeDefault, out PooledByteBufferWriter output);
try
{
WriteTo(writer);
writer.Flush();
return JsonElement.ParseValue(output.WrittenMemory.Span, options: default).ValueKind;
}
finally
{
Utf8JsonWriterCache.ReturnWriterAndBuffer(writer, output);
}
}

internal sealed override bool DeepEqualsCore(JsonNode? otherNode)
Expand Down Expand Up @@ -107,9 +116,21 @@ internal sealed override bool DeepEqualsCore(JsonNode? otherNode)
}
}

using PooledByteBufferWriter thisOutput = WriteToPooledBuffer();
using PooledByteBufferWriter otherOutput = otherNode.WriteToPooledBuffer();
using PooledByteBufferWriter thisOutput = WriteToPooledBuffer(this);
using PooledByteBufferWriter otherOutput = WriteToPooledBuffer(otherNode);
return thisOutput.WrittenMemory.Span.SequenceEqual(otherOutput.WrittenMemory.Span);

static PooledByteBufferWriter WriteToPooledBuffer(
JsonNode node,
JsonSerializerOptions? options = null,
JsonWriterOptions writerOptions = default,
int bufferSize = JsonSerializerOptions.BufferSizeDefault)
{
var bufferWriter = new PooledByteBufferWriter(bufferSize);
using var writer = new Utf8JsonWriter(bufferWriter, writerOptions);
node.WriteTo(writer, options);
return bufferWriter;
}
}

internal TypeToConvert ConvertJsonElement<TypeToConvert>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ internal static class Utf8JsonWriterCache
[ThreadStatic]
private static ThreadLocalState? t_threadLocalState;

public static Utf8JsonWriter RentWriterAndBuffer(JsonSerializerOptions options, out PooledByteBufferWriter bufferWriter)
public static Utf8JsonWriter RentWriterAndBuffer(JsonSerializerOptions options, out PooledByteBufferWriter bufferWriter) =>
RentWriterAndBuffer(options.GetWriterOptions(), options.DefaultBufferSize, out bufferWriter);

public static Utf8JsonWriter RentWriterAndBuffer(JsonWriterOptions options, int defaultBufferSize, out PooledByteBufferWriter bufferWriter)
{
ThreadLocalState state = t_threadLocalState ??= new();
Utf8JsonWriter writer;
Expand All @@ -24,14 +27,14 @@ public static Utf8JsonWriter RentWriterAndBuffer(JsonSerializerOptions options,
bufferWriter = state.BufferWriter;
writer = state.Writer;

bufferWriter.InitializeEmptyInstance(options.DefaultBufferSize);
writer.Reset(bufferWriter, options.GetWriterOptions());
bufferWriter.InitializeEmptyInstance(defaultBufferSize);
writer.Reset(bufferWriter, options);
}
else
{
// We're in a recursive JsonSerializer call -- return fresh instances.
bufferWriter = new PooledByteBufferWriter(options.DefaultBufferSize);
writer = new Utf8JsonWriter(bufferWriter, options.GetWriterOptions());
bufferWriter = new PooledByteBufferWriter(defaultBufferSize);
writer = new Utf8JsonWriter(bufferWriter, options);
}

return writer;
Expand Down