From b76ef7fa73c758daaa663a4d36d78d536df152fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Habinshuti?= Date: Tue, 30 Jan 2024 15:40:48 +0300 Subject: [PATCH] Remove buffer copy when writing base64 JSON value (#97687) --- .../Utf8JsonWriter.WriteProperties.Bytes.cs | 8 +++---- .../Utf8JsonWriter.WriteValues.Bytes.cs | 4 ++-- .../Utf8JsonWriter.WriteValues.Helpers.cs | 22 +++---------------- 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs index a8d53aef63dec..1a1b3edb2ca80 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs @@ -236,7 +236,7 @@ private void WriteBase64Minimized(ReadOnlySpan escapedPropertyName, ReadOn output[BytesPending++] = JsonConstants.Quote; - Base64EncodeAndWrite(bytes, output, encodedLength); + Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } @@ -272,7 +272,7 @@ private void WriteBase64Minimized(ReadOnlySpan escapedPropertyName, ReadOn output[BytesPending++] = JsonConstants.Quote; - Base64EncodeAndWrite(bytes, output, encodedLength); + Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } @@ -322,7 +322,7 @@ private void WriteBase64Indented(ReadOnlySpan escapedPropertyName, ReadOnl output[BytesPending++] = JsonConstants.Quote; - Base64EncodeAndWrite(bytes, output, encodedLength); + Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } @@ -373,7 +373,7 @@ private void WriteBase64Indented(ReadOnlySpan escapedPropertyName, ReadOnl output[BytesPending++] = JsonConstants.Quote; - Base64EncodeAndWrite(bytes, output, encodedLength); + Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs index 31500fb2b00ec..e4b4a877bbd56 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Bytes.cs @@ -79,7 +79,7 @@ private void WriteBase64Minimized(ReadOnlySpan bytes) } output[BytesPending++] = JsonConstants.Quote; - Base64EncodeAndWrite(bytes, output, encodingLength); + Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } @@ -130,7 +130,7 @@ private void WriteBase64Indented(ReadOnlySpan bytes) output[BytesPending++] = JsonConstants.Quote; - Base64EncodeAndWrite(bytes, output, encodingLength); + Base64EncodeAndWrite(bytes, output); output[BytesPending++] = JsonConstants.Quote; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs index 731e62867f2cb..eeee39e0447d6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs @@ -35,29 +35,13 @@ private void ValidateWritingValue() } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Base64EncodeAndWrite(ReadOnlySpan bytes, Span output, int encodingLength) + private void Base64EncodeAndWrite(ReadOnlySpan bytes, Span output) { - byte[]? outputText = null; - - Span encodedBytes = encodingLength <= JsonConstants.StackallocByteThreshold ? - stackalloc byte[JsonConstants.StackallocByteThreshold] : - (outputText = ArrayPool.Shared.Rent(encodingLength)); - - OperationStatus status = Base64.EncodeToUtf8(bytes, encodedBytes, out int consumed, out int written); + Span destination = output.Slice(BytesPending); + OperationStatus status = Base64.EncodeToUtf8(bytes, destination, out int consumed, out int written); Debug.Assert(status == OperationStatus.Done); Debug.Assert(consumed == bytes.Length); - - encodedBytes = encodedBytes.Slice(0, written); - Span destination = output.Slice(BytesPending); - - Debug.Assert(destination.Length >= written); - encodedBytes.Slice(0, written).CopyTo(destination); BytesPending += written; - - if (outputText != null) - { - ArrayPool.Shared.Return(outputText); - } } } }