Use more pooled Utf8BufferTextReaders (#1728)

- Use it in the HandshakeProtocol
- Move CreateJsonTextReader to JsonUtils
This commit is contained in:
David Fowler 2018-03-26 23:32:43 -07:00 committed by GitHub
parent cc52beec17
commit b78e70fadb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 33 deletions

View File

@ -56,33 +56,32 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
return new JsonTextWriter(new StreamWriter(output, _utf8NoBom, 1024, leaveOpen: true)); return new JsonTextWriter(new StreamWriter(output, _utf8NoBom, 1024, leaveOpen: true));
} }
private static JsonTextReader CreateJsonTextReader(ReadOnlyMemory<byte> payload)
{
var textReader = new Utf8BufferTextReader();
textReader.SetBuffer(payload);
var reader = new JsonTextReader(textReader);
reader.ArrayPool = JsonArrayPool<char>.Shared;
return reader;
}
public static HandshakeResponseMessage ParseResponseMessage(ReadOnlyMemory<byte> payload) public static HandshakeResponseMessage ParseResponseMessage(ReadOnlyMemory<byte> payload)
{ {
using (var reader = CreateJsonTextReader(payload)) var textReader = Utf8BufferTextReader.Get(payload);
try
{ {
var token = JToken.ReadFrom(reader); using (var reader = JsonUtils.CreateJsonTextReader(textReader))
var handshakeJObject = JsonUtils.GetObject(token);
// a handshake response does not have a type
// check the incoming message was not any other type of message
var type = JsonUtils.GetOptionalProperty<string>(handshakeJObject, TypePropertyName);
if (!string.IsNullOrEmpty(type))
{ {
throw new InvalidOperationException("Handshake response should not have a 'type' value."); var token = JToken.ReadFrom(reader);
} var handshakeJObject = JsonUtils.GetObject(token);
var error = JsonUtils.GetOptionalProperty<string>(handshakeJObject, ErrorPropertyName); // a handshake response does not have a type
return new HandshakeResponseMessage(error); // check the incoming message was not any other type of message
var type = JsonUtils.GetOptionalProperty<string>(handshakeJObject, TypePropertyName);
if (!string.IsNullOrEmpty(type))
{
throw new InvalidOperationException("Handshake response should not have a 'type' value.");
}
var error = JsonUtils.GetOptionalProperty<string>(handshakeJObject, ErrorPropertyName);
return new HandshakeResponseMessage(error);
}
}
finally
{
Utf8BufferTextReader.Return(textReader);
} }
} }
@ -99,13 +98,21 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
throw new InvalidDataException("Unable to parse payload as a handshake request message."); throw new InvalidDataException("Unable to parse payload as a handshake request message.");
} }
using (var reader = CreateJsonTextReader(payload)) var textReader = Utf8BufferTextReader.Get(payload);
try
{ {
var token = JToken.ReadFrom(reader); using (var reader = JsonUtils.CreateJsonTextReader(textReader))
var handshakeJObject = JsonUtils.GetObject(token); {
var protocol = JsonUtils.GetRequiredProperty<string>(handshakeJObject, ProtocolPropertyName); var token = JToken.ReadFrom(reader);
var protocolVersion = JsonUtils.GetRequiredProperty<int>(handshakeJObject, ProtocolVersionName, JTokenType.Integer); var handshakeJObject = JsonUtils.GetObject(token);
requestMessage = new HandshakeRequestMessage(protocol, protocolVersion); var protocol = JsonUtils.GetRequiredProperty<string>(handshakeJObject, ProtocolPropertyName);
var protocolVersion = JsonUtils.GetRequiredProperty<int>(handshakeJObject, ProtocolVersionName, JTokenType.Integer);
requestMessage = new HandshakeRequestMessage(protocol, protocolVersion);
}
}
finally
{
Utf8BufferTextReader.Return(textReader);
} }
return true; return true;

View File

@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
TextMessageFormatter.WriteRecordSeparator(output); TextMessageFormatter.WriteRecordSeparator(output);
} }
private HubMessage ParseMessage(TextReader textReader, IInvocationBinder binder) private HubMessage ParseMessage(Utf8BufferTextReader textReader, IInvocationBinder binder)
{ {
try try
{ {
@ -108,11 +108,8 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
Dictionary<string, string> headers = null; Dictionary<string, string> headers = null;
var completed = false; var completed = false;
using (var reader = new JsonTextReader(textReader)) using (var reader = JsonUtils.CreateJsonTextReader(textReader))
{ {
reader.ArrayPool = JsonArrayPool<char>.Shared;
reader.CloseInput = false;
JsonUtils.CheckRead(reader); JsonUtils.CheckRead(reader);
// We're always parsing a JSON object // We're always parsing a JSON object

View File

@ -10,6 +10,17 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
{ {
public static class JsonUtils public static class JsonUtils
{ {
internal static JsonTextReader CreateJsonTextReader(Utf8BufferTextReader textReader)
{
var reader = new JsonTextReader(textReader);
reader.ArrayPool = JsonArrayPool<char>.Shared;
// Don't close the output, Utf8BufferTextReader is resettable
reader.CloseInput = false;
return reader;
}
public static JObject GetObject(JToken token) public static JObject GetObject(JToken token)
{ {
if (token == null || token.Type != JTokenType.Object) if (token == null || token.Type != JTokenType.Object)