From 8782c2727f80020eeed96841450bd849cc1e0539 Mon Sep 17 00:00:00 2001 From: Albie Date: Fri, 27 Aug 2021 09:09:51 +0100 Subject: [PATCH] add arraypool support to file downloads and json deserialization --- .../DragonFruit.Common.Data.Tests.csproj | 2 +- DragonFruit.Common.Data/ApiClient.cs | 10 +++++---- .../DragonFruit.Common.Data.csproj | 1 + .../Serializers/ApiJsonSerializer.cs | 22 ++++++++++++++++++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/DragonFruit.Common.Data.Tests/DragonFruit.Common.Data.Tests.csproj b/DragonFruit.Common.Data.Tests/DragonFruit.Common.Data.Tests.csproj index 36621a5..e4f2a80 100644 --- a/DragonFruit.Common.Data.Tests/DragonFruit.Common.Data.Tests.csproj +++ b/DragonFruit.Common.Data.Tests/DragonFruit.Common.Data.Tests.csproj @@ -12,6 +12,6 @@ - + diff --git a/DragonFruit.Common.Data/ApiClient.cs b/DragonFruit.Common.Data/ApiClient.cs index 67864d5..22630bb 100644 --- a/DragonFruit.Common.Data/ApiClient.cs +++ b/DragonFruit.Common.Data/ApiClient.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. Please refer to the LICENSE file at the root of this project for details using System; +using System.Buffers; using System.Globalization; using System.IO; using System.Linq; @@ -267,8 +268,8 @@ HttpResponseMessage CopyProcess(HttpResponseMessage response) using var networkStream = response.Content.ReadAsStreamAsync().Result; #endif - // create a buffer for progress reporting - var buffer = new byte[request.BufferSize]; + // rent a buffer for progress reporting + var buffer = ArrayPool.Shared.Rent(request.BufferSize); int count; int iterations = 0; @@ -282,10 +283,11 @@ HttpResponseMessage CopyProcess(HttpResponseMessage response) progressUpdated?.Invoke(stream.Length, response.Content.Headers.ContentLength); } - // flush, send a final update and return + // flush, return buffer and send a final update stream.Flush(); - progressUpdated?.Invoke(stream.Length, response.Content.Headers.ContentLength); + ArrayPool.Shared.Return(buffer); + progressUpdated?.Invoke(stream.Length, response.Content.Headers.ContentLength); return response; } diff --git a/DragonFruit.Common.Data/DragonFruit.Common.Data.csproj b/DragonFruit.Common.Data/DragonFruit.Common.Data.csproj index 936727e..e6babf6 100644 --- a/DragonFruit.Common.Data/DragonFruit.Common.Data.csproj +++ b/DragonFruit.Common.Data/DragonFruit.Common.Data.csproj @@ -24,6 +24,7 @@ + diff --git a/DragonFruit.Common.Data/Serializers/ApiJsonSerializer.cs b/DragonFruit.Common.Data/Serializers/ApiJsonSerializer.cs index c6f9309..87125d5 100644 --- a/DragonFruit.Common.Data/Serializers/ApiJsonSerializer.cs +++ b/DragonFruit.Common.Data/Serializers/ApiJsonSerializer.cs @@ -1,6 +1,7 @@ // DragonFruit.Common Copyright 2020 DragonFruit Network // Licensed under the MIT License. Please refer to the LICENSE file at the root of this project for details +using System.Buffers; using System.Globalization; using System.IO; using System.Net.Http; @@ -80,6 +81,7 @@ public HttpContent Serialize(T input) where T : class using (var streamWriter = new StreamWriter(stream, Encoding, 4096, true)) using (var jsonWriter = new JsonTextWriter(streamWriter)) { + jsonWriter.ArrayPool = JsonArrayPool.Instance; Serializer.Serialize(jsonWriter, input); } @@ -95,9 +97,27 @@ public T Deserialize(Stream input) where T : class false when Encoding is null => new StreamReader(input), false => new StreamReader(input, Encoding) }; - using var reader = new JsonTextReader(sr); + + using var reader = new JsonTextReader(sr) + { + ArrayPool = JsonArrayPool.Instance + }; return Serializer.Deserialize(reader); } } + + /// + /// A wrapper for the that implements + /// + /// + /// Taken from https://github.com/JamesNK/Newtonsoft.Json/blob/52e257ee57899296d81a868b32300f0b3cfeacbe/Src/Newtonsoft.Json.Tests/DemoTests.cs#L709 + /// + internal class JsonArrayPool : IArrayPool + { + public static readonly JsonArrayPool Instance = new JsonArrayPool(); + + public char[] Rent(int minimumLength) => ArrayPool.Shared.Rent(minimumLength); + public void Return(char[] array) => ArrayPool.Shared.Return(array); + } }