Copy Kestrel perf changes (#7480)
This commit is contained in:
parent
d1aa53721b
commit
9de42d516e
|
|
@ -13,6 +13,7 @@
|
|||
<Compile Include="$(SignalRSharedSourceRoot)PipeWriterStream.cs" Link="PipeWriterStream.cs" />
|
||||
<Compile Include="$(SignalRSharedSourceRoot)ReflectionHelper.cs" Link="ReflectionHelper.cs" />
|
||||
<Compile Include="$(SignalRSharedSourceRoot)TimerAwaitable.cs" Link="Internal\TimerAwaitable.cs" />
|
||||
<Compile Include="$(SignalRSharedSourceRoot)ValueTaskExtensions.cs" Link="Internal\ValueTaskExtensions.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal
|
|||
private const byte ByteLF = (byte)'\n';
|
||||
private const byte ByteColon = (byte)':';
|
||||
|
||||
private static readonly byte[] _dataPrefix = Encoding.UTF8.GetBytes("data: ");
|
||||
private static readonly byte[] _sseLineEnding = Encoding.UTF8.GetBytes("\r\n");
|
||||
private static ReadOnlySpan<byte> _dataPrefix => new byte[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a', (byte)':', (byte)' ' };
|
||||
private static ReadOnlySpan<byte> _sseLineEnding => new byte[] { (byte)'\r', (byte)'\n' };
|
||||
private static readonly byte[] _newLine = Encoding.UTF8.GetBytes(Environment.NewLine);
|
||||
|
||||
private InternalParseState _internalParserState = InternalParseState.ReadMessagePayload;
|
||||
|
|
|
|||
|
|
@ -13,24 +13,25 @@ namespace Microsoft.AspNetCore.Http.Connections
|
|||
{
|
||||
public static class NegotiateProtocol
|
||||
{
|
||||
// Use C#7.3's ReadOnlySpan<byte> optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/
|
||||
private const string ConnectionIdPropertyName = "connectionId";
|
||||
private static readonly byte[] ConnectionIdPropertyNameBytes = Encoding.UTF8.GetBytes(ConnectionIdPropertyName);
|
||||
private static ReadOnlySpan<byte> ConnectionIdPropertyNameBytes => new byte[] { (byte)'c', (byte)'o', (byte)'n', (byte)'n', (byte)'e', (byte)'c', (byte)'t', (byte)'i', (byte)'o', (byte)'n', (byte)'I', (byte)'d' };
|
||||
private const string UrlPropertyName = "url";
|
||||
private static readonly byte[] UrlPropertyNameBytes = Encoding.UTF8.GetBytes(UrlPropertyName);
|
||||
private static ReadOnlySpan<byte> UrlPropertyNameBytes => new byte[] { (byte)'u', (byte)'r', (byte)'l' };
|
||||
private const string AccessTokenPropertyName = "accessToken";
|
||||
private static readonly byte[] AccessTokenPropertyNameBytes = Encoding.UTF8.GetBytes(AccessTokenPropertyName);
|
||||
private static ReadOnlySpan<byte> AccessTokenPropertyNameBytes => new byte[] { (byte)'a', (byte)'c', (byte)'c', (byte)'e', (byte)'s', (byte)'s', (byte)'T', (byte)'o', (byte)'k', (byte)'e', (byte)'n' };
|
||||
private const string AvailableTransportsPropertyName = "availableTransports";
|
||||
private static readonly byte[] AvailableTransportsPropertyNameBytes = Encoding.UTF8.GetBytes(AvailableTransportsPropertyName);
|
||||
private static ReadOnlySpan<byte> AvailableTransportsPropertyNameBytes => new byte[] { (byte)'a', (byte)'v', (byte)'a', (byte)'i', (byte)'l', (byte)'a', (byte)'b', (byte)'l', (byte)'e', (byte)'T', (byte)'r', (byte)'a', (byte)'n', (byte)'s', (byte)'p', (byte)'o', (byte)'r', (byte)'t', (byte)'s' };
|
||||
private const string TransportPropertyName = "transport";
|
||||
private static readonly byte[] TransportPropertyNameBytes = Encoding.UTF8.GetBytes(TransportPropertyName);
|
||||
private static ReadOnlySpan<byte> TransportPropertyNameBytes => new byte[] { (byte)'t', (byte)'r', (byte)'a', (byte)'n', (byte)'s', (byte)'p', (byte)'o', (byte)'r', (byte)'t' };
|
||||
private const string TransferFormatsPropertyName = "transferFormats";
|
||||
private static readonly byte[] TransferFormatsPropertyNameBytes = Encoding.UTF8.GetBytes(TransferFormatsPropertyName);
|
||||
private static ReadOnlySpan<byte> TransferFormatsPropertyNameBytes => new byte[] { (byte)'t', (byte)'r', (byte)'a', (byte)'n', (byte)'s', (byte)'f', (byte)'e', (byte)'r', (byte)'F', (byte)'o', (byte)'r', (byte)'m', (byte)'a', (byte)'t', (byte)'s' };
|
||||
private const string ErrorPropertyName = "error";
|
||||
private static readonly byte[] ErrorPropertyNameBytes = Encoding.UTF8.GetBytes(ErrorPropertyName);
|
||||
private static ReadOnlySpan<byte> ErrorPropertyNameBytes => new byte[] { (byte)'e', (byte)'r', (byte)'r', (byte)'o', (byte)'r' };
|
||||
|
||||
// Used to detect ASP.NET SignalR Server connection attempt
|
||||
private const string ProtocolVersionPropertyName = "ProtocolVersion";
|
||||
private static readonly byte[] ProtocolVersionPropertyNameBytes = Encoding.UTF8.GetBytes(ProtocolVersionPropertyName);
|
||||
private static ReadOnlySpan<byte> ProtocolVersionPropertyNameBytes => new byte[] { (byte)'P', (byte)'r', (byte)'o', (byte)'t', (byte)'o', (byte)'c', (byte)'o', (byte)'l', (byte)'V', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n' };
|
||||
|
||||
public static void WriteResponse(NegotiationResponse response, IBufferWriter<byte> output)
|
||||
{
|
||||
|
|
@ -114,15 +115,15 @@ namespace Microsoft.AspNetCore.Http.Connections
|
|||
|
||||
if (memberName.SequenceEqual(UrlPropertyNameBytes))
|
||||
{
|
||||
url = reader.ReadAsString(UrlPropertyNameBytes);
|
||||
url = reader.ReadAsString(UrlPropertyName);
|
||||
}
|
||||
else if (memberName.SequenceEqual(AccessTokenPropertyNameBytes))
|
||||
{
|
||||
accessToken = reader.ReadAsString(AccessTokenPropertyNameBytes);
|
||||
accessToken = reader.ReadAsString(AccessTokenPropertyName);
|
||||
}
|
||||
else if (memberName.SequenceEqual(ConnectionIdPropertyNameBytes))
|
||||
{
|
||||
connectionId = reader.ReadAsString(ConnectionIdPropertyNameBytes);
|
||||
connectionId = reader.ReadAsString(ConnectionIdPropertyName);
|
||||
}
|
||||
else if (memberName.SequenceEqual(AvailableTransportsPropertyNameBytes))
|
||||
{
|
||||
|
|
@ -144,7 +145,7 @@ namespace Microsoft.AspNetCore.Http.Connections
|
|||
}
|
||||
else if (memberName.SequenceEqual(ErrorPropertyNameBytes))
|
||||
{
|
||||
error = reader.ReadAsString(ErrorPropertyNameBytes);
|
||||
error = reader.ReadAsString(ErrorPropertyName);
|
||||
}
|
||||
else if (memberName.SequenceEqual(ProtocolVersionPropertyNameBytes))
|
||||
{
|
||||
|
|
@ -215,7 +216,7 @@ namespace Microsoft.AspNetCore.Http.Connections
|
|||
|
||||
if (memberName.SequenceEqual(TransportPropertyNameBytes))
|
||||
{
|
||||
availableTransport.Transport = reader.ReadAsString(TransportPropertyNameBytes);
|
||||
availableTransport.Transport = reader.ReadAsString(TransportPropertyName);
|
||||
}
|
||||
else if (memberName.SequenceEqual(TransferFormatsPropertyNameBytes))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
<Compile Include="$(SignalRSharedSourceRoot)WebSocketExtensions.cs" Link="WebSocketExtensions.cs" />
|
||||
<Compile Include="$(SignalRSharedSourceRoot)StreamExtensions.cs" Link="StreamExtensions.cs" />
|
||||
<Compile Include="$(SignalRSharedSourceRoot)DuplexPipe.cs" Link="DuplexPipe.cs" />
|
||||
<Compile Include="$(SignalRSharedSourceRoot)ValueTaskExtensions.cs" Link="ValueTaskExtensions.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Buffers;
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
|
||||
namespace System.IO.Pipelines
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
|
@ -70,19 +71,19 @@ namespace Microsoft.AspNetCore.Internal
|
|||
}
|
||||
}
|
||||
|
||||
public static string ReadAsString(this ref Utf8JsonReader reader, byte[] propertyName)
|
||||
public static string ReadAsString(this ref Utf8JsonReader reader, string propertyName)
|
||||
{
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType != JsonTokenType.String)
|
||||
{
|
||||
throw new InvalidDataException($"Expected '{Encoding.UTF8.GetString(propertyName)}' to be of type {JsonTokenType.String}.");
|
||||
throw new InvalidDataException($"Expected '{propertyName}' to be of type {JsonTokenType.String}.");
|
||||
}
|
||||
|
||||
return reader.GetString();
|
||||
}
|
||||
|
||||
public static int? ReadAsInt32(this ref Utf8JsonReader reader, byte[] propertyName)
|
||||
public static int? ReadAsInt32(this ref Utf8JsonReader reader, string propertyName)
|
||||
{
|
||||
reader.Read();
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ namespace Microsoft.AspNetCore.Internal
|
|||
|
||||
if (reader.TokenType != JsonTokenType.Number)
|
||||
{
|
||||
throw new InvalidDataException($"Expected '{Encoding.UTF8.GetString(propertyName)}' to be of type {JsonTokenType.Number}.");
|
||||
throw new InvalidDataException($"Expected '{propertyName}' to be of type {JsonTokenType.Number}.");
|
||||
}
|
||||
|
||||
return reader.GetInt32();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO.Pipelines;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Internal
|
||||
{
|
||||
internal static class ValueTaskExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Task GetAsTask(this in ValueTask<FlushResult> valueTask)
|
||||
{
|
||||
// Try to avoid the allocation from AsTask
|
||||
if (valueTask.IsCompletedSuccessfully)
|
||||
{
|
||||
// Signal consumption to the IValueTaskSource
|
||||
valueTask.GetAwaiter().GetResult();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
return valueTask.AsTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,16 +17,17 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
|
|||
/// </summary>
|
||||
public static class HandshakeProtocol
|
||||
{
|
||||
// Use C#7.3's ReadOnlySpan<byte> optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/
|
||||
private const string ProtocolPropertyName = "protocol";
|
||||
private static readonly byte[] ProtocolPropertyNameBytes = Encoding.UTF8.GetBytes(ProtocolPropertyName);
|
||||
private static ReadOnlySpan<byte> ProtocolPropertyNameBytes => new byte[] { (byte)'p', (byte)'r', (byte)'o', (byte)'t', (byte)'o', (byte)'c', (byte)'o', (byte)'l' };
|
||||
private const string ProtocolVersionPropertyName = "version";
|
||||
private static readonly byte[] ProtocolVersionPropertyNameBytes = Encoding.UTF8.GetBytes(ProtocolVersionPropertyName);
|
||||
private static ReadOnlySpan<byte> ProtocolVersionPropertyNameBytes => new byte[] { (byte)'v', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n' };
|
||||
private const string MinorVersionPropertyName = "minorVersion";
|
||||
private static readonly byte[] MinorVersionPropertyNameBytes = Encoding.UTF8.GetBytes(MinorVersionPropertyName);
|
||||
private static ReadOnlySpan<byte> MinorVersionPropertyNameBytes => new byte[] { (byte)'m', (byte)'i', (byte)'n', (byte)'o', (byte)'r', (byte)'V', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n' };
|
||||
private const string ErrorPropertyName = "error";
|
||||
private static readonly byte[] ErrorPropertyNameBytes = Encoding.UTF8.GetBytes(ErrorPropertyName);
|
||||
private static ReadOnlySpan<byte> ErrorPropertyNameBytes => new byte[] { (byte)'e', (byte)'r', (byte)'r', (byte)'o', (byte)'r' };
|
||||
private const string TypePropertyName = "type";
|
||||
private static readonly byte[] TypePropertyNameBytes = Encoding.UTF8.GetBytes(TypePropertyName);
|
||||
private static ReadOnlySpan<byte> TypePropertyNameBytes => new byte[] { (byte)'t', (byte)'y', (byte)'p', (byte)'e' };
|
||||
|
||||
private static ConcurrentDictionary<IHubProtocol, ReadOnlyMemory<byte>> _messageCache = new ConcurrentDictionary<IHubProtocol, ReadOnlyMemory<byte>>();
|
||||
|
||||
|
|
@ -128,11 +129,11 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
|
|||
}
|
||||
else if (memberName.SequenceEqual(ErrorPropertyNameBytes))
|
||||
{
|
||||
error = reader.ReadAsString(ErrorPropertyNameBytes);
|
||||
error = reader.ReadAsString(ErrorPropertyName);
|
||||
}
|
||||
else if (memberName.SequenceEqual(MinorVersionPropertyNameBytes))
|
||||
{
|
||||
minorVersion = reader.ReadAsInt32(MinorVersionPropertyNameBytes);
|
||||
minorVersion = reader.ReadAsInt32(MinorVersionPropertyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -183,11 +184,11 @@ namespace Microsoft.AspNetCore.SignalR.Protocol
|
|||
|
||||
if (memberName.SequenceEqual(ProtocolPropertyNameBytes))
|
||||
{
|
||||
protocol = reader.ReadAsString(ProtocolPropertyNameBytes);
|
||||
protocol = reader.ReadAsString(ProtocolPropertyName);
|
||||
}
|
||||
else if (memberName.SequenceEqual(ProtocolVersionPropertyNameBytes))
|
||||
{
|
||||
protocolVersion = reader.ReadAsInt32(ProtocolVersionPropertyNameBytes);
|
||||
protocolVersion = reader.ReadAsInt32(ProtocolVersionPropertyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Internal;
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR
|
||||
|
|
|
|||
Loading…
Reference in New Issue