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.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
@ -86,44 +87,49 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
public override void Write(char value)
{
var destination = GetBuffer();
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++;
}
else
{
// Json.NET only writes ASCII characters by themselves, e.g. {}[], etc
// this should be an exceptional case
var bytesUsed = 0;
var charsUsed = 0;
unsafe
{
#if NETCOREAPP2_1
_encoder.Convert(new Span<char>(&value, 1), destination, false, out charsUsed, out bytesUsed, out _);
#else
fixed (byte* destinationBytes = &MemoryMarshal.GetReference(destination))
{
_encoder.Convert(&value, 1, destinationBytes, destination.Length, false, out charsUsed, out bytesUsed, out _);
}
#endif
}
Debug.Assert(charsUsed == 1);
if (bytesUsed > 0)
{
_memoryUsed += bytesUsed;
}
WriteMultiByteChar(value);
}
}
private unsafe void WriteMultiByteChar(char value)
{
var destination = GetBuffer();
// Json.NET only writes ASCII characters by themselves, e.g. {}[], etc
// this should be an exceptional case
var bytesUsed = 0;
var charsUsed = 0;
#if NETCOREAPP2_1
_encoder.Convert(new Span<char>(&value, 1), destination, false, out charsUsed, out bytesUsed, out _);
#else
fixed (byte* destinationBytes = &MemoryMarshal.GetReference(destination))
{
_encoder.Convert(&value, 1, destinationBytes, destination.Length, false, out charsUsed, out bytesUsed, out _);
}
#endif
Debug.Assert(charsUsed == 1);
_memoryUsed += bytesUsed;
}
public override void Write(string value)
{
WriteInternal(value.AsSpan());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Span<byte> GetBuffer()
{
EnsureBuffer();