From b78e70fadb025e8269b82b1f0589b78f705417a3 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Mon, 26 Mar 2018 23:32:43 -0700 Subject: [PATCH] Use more pooled Utf8BufferTextReaders (#1728) - Use it in the HandshakeProtocol - Move CreateJsonTextReader to JsonUtils --- .../Internal/Protocol/HandshakeProtocol.cs | 63 ++++++++++--------- .../Internal/Protocol/JsonHubProtocol.cs | 7 +-- .../Internal/Protocol/JsonUtils.cs | 11 ++++ 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/HandshakeProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/HandshakeProtocol.cs index 8efbee6a26..2ddc5a8f4a 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/HandshakeProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/HandshakeProtocol.cs @@ -56,33 +56,32 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol return new JsonTextWriter(new StreamWriter(output, _utf8NoBom, 1024, leaveOpen: true)); } - private static JsonTextReader CreateJsonTextReader(ReadOnlyMemory payload) - { - var textReader = new Utf8BufferTextReader(); - textReader.SetBuffer(payload); - var reader = new JsonTextReader(textReader); - reader.ArrayPool = JsonArrayPool.Shared; - - return reader; - } - public static HandshakeResponseMessage ParseResponseMessage(ReadOnlyMemory payload) { - using (var reader = CreateJsonTextReader(payload)) + var textReader = Utf8BufferTextReader.Get(payload); + + try { - var token = JToken.ReadFrom(reader); - 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(handshakeJObject, TypePropertyName); - if (!string.IsNullOrEmpty(type)) + using (var reader = JsonUtils.CreateJsonTextReader(textReader)) { - 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(handshakeJObject, ErrorPropertyName); - return new HandshakeResponseMessage(error); + // a handshake response does not have a type + // check the incoming message was not any other type of message + var type = JsonUtils.GetOptionalProperty(handshakeJObject, TypePropertyName); + if (!string.IsNullOrEmpty(type)) + { + throw new InvalidOperationException("Handshake response should not have a 'type' value."); + } + + var error = JsonUtils.GetOptionalProperty(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."); } - using (var reader = CreateJsonTextReader(payload)) + var textReader = Utf8BufferTextReader.Get(payload); + try { - var token = JToken.ReadFrom(reader); - var handshakeJObject = JsonUtils.GetObject(token); - var protocol = JsonUtils.GetRequiredProperty(handshakeJObject, ProtocolPropertyName); - var protocolVersion = JsonUtils.GetRequiredProperty(handshakeJObject, ProtocolVersionName, JTokenType.Integer); - requestMessage = new HandshakeRequestMessage(protocol, protocolVersion); + using (var reader = JsonUtils.CreateJsonTextReader(textReader)) + { + var token = JToken.ReadFrom(reader); + var handshakeJObject = JsonUtils.GetObject(token); + var protocol = JsonUtils.GetRequiredProperty(handshakeJObject, ProtocolPropertyName); + var protocolVersion = JsonUtils.GetRequiredProperty(handshakeJObject, ProtocolVersionName, JTokenType.Integer); + requestMessage = new HandshakeRequestMessage(protocol, protocolVersion); + } + } + finally + { + Utf8BufferTextReader.Return(textReader); } return true; diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs index 80d7e56440..f46117dca7 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonHubProtocol.cs @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol TextMessageFormatter.WriteRecordSeparator(output); } - private HubMessage ParseMessage(TextReader textReader, IInvocationBinder binder) + private HubMessage ParseMessage(Utf8BufferTextReader textReader, IInvocationBinder binder) { try { @@ -108,11 +108,8 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol Dictionary headers = null; var completed = false; - using (var reader = new JsonTextReader(textReader)) + using (var reader = JsonUtils.CreateJsonTextReader(textReader)) { - reader.ArrayPool = JsonArrayPool.Shared; - reader.CloseInput = false; - JsonUtils.CheckRead(reader); // We're always parsing a JSON object diff --git a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonUtils.cs b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonUtils.cs index ef6ec3f442..37ce8d8d85 100644 --- a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonUtils.cs +++ b/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/JsonUtils.cs @@ -10,6 +10,17 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol { public static class JsonUtils { + internal static JsonTextReader CreateJsonTextReader(Utf8BufferTextReader textReader) + { + var reader = new JsonTextReader(textReader); + reader.ArrayPool = JsonArrayPool.Shared; + + // Don't close the output, Utf8BufferTextReader is resettable + reader.CloseInput = false; + + return reader; + } + public static JObject GetObject(JToken token) { if (token == null || token.Type != JTokenType.Object)