Improve writing single characters with UTF8 text writer (#1814)

This commit is contained in:
James Newton-King 2018-04-01 17:34:19 +12:00 committed by GitHub
parent e6e45cea05
commit ca161e9bc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 30 additions and 24 deletions

View File

@ -5,6 +5,7 @@ using System;
using System.Buffers; using System.Buffers;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@ -86,21 +87,29 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
public override void Write(char value) public override void Write(char value)
{ {
var destination = GetBuffer();
if (value <= 127) if (value <= 127)
{ {
destination[0] = (byte)value; EnsureBuffer();
// Only need to set one byte
// Avoid Memory<T>.Slice overhead for perf
_memory.Span[_memoryUsed] = (byte)value;
_memoryUsed++; _memoryUsed++;
} }
else else
{ {
WriteMultiByteChar(value);
}
}
private unsafe void WriteMultiByteChar(char value)
{
var destination = GetBuffer();
// Json.NET only writes ASCII characters by themselves, e.g. {}[], etc // Json.NET only writes ASCII characters by themselves, e.g. {}[], etc
// this should be an exceptional case // this should be an exceptional case
var bytesUsed = 0; var bytesUsed = 0;
var charsUsed = 0; var charsUsed = 0;
unsafe
{
#if NETCOREAPP2_1 #if NETCOREAPP2_1
_encoder.Convert(new Span<char>(&value, 1), destination, false, out charsUsed, out bytesUsed, out _); _encoder.Convert(new Span<char>(&value, 1), destination, false, out charsUsed, out bytesUsed, out _);
#else #else
@ -109,21 +118,18 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
_encoder.Convert(&value, 1, destinationBytes, destination.Length, false, out charsUsed, out bytesUsed, out _); _encoder.Convert(&value, 1, destinationBytes, destination.Length, false, out charsUsed, out bytesUsed, out _);
} }
#endif #endif
}
Debug.Assert(charsUsed == 1); Debug.Assert(charsUsed == 1);
if (bytesUsed > 0)
{
_memoryUsed += bytesUsed; _memoryUsed += bytesUsed;
} }
}
}
public override void Write(string value) public override void Write(string value)
{ {
WriteInternal(value.AsSpan()); WriteInternal(value.AsSpan());
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Span<byte> GetBuffer() private Span<byte> GetBuffer()
{ {
EnsureBuffer(); EnsureBuffer();