Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

Commit 1d76284

Browse files
Brad ChristensenSteveSandersonMS
authored andcommitted
Serialize node invocationInfo JSON directly to stream to avoid running out of memory
Fixed only for SocketNodeInstance, as it deals nicely with streams. Previously ~30MB of JSON text and 32-bit IIS Express would result in an OutOfMemoryException at the GetBytes method, which is now fixed by writing the JSON string directly to the stream and not handling it as a string in between.
1 parent c33b227 commit 1d76284

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

src/Microsoft.AspNetCore.NodeServices/HostingModels/SocketNodeInstance.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ internal class SocketNodeInstance : OutOfProcessNodeInstance
3333
TypeNameHandling = TypeNameHandling.None
3434
};
3535

36+
private readonly static int streamBufferSize = 16 * 1024;
37+
private readonly static UTF8Encoding utf8EncodingWithoutBom = new UTF8Encoding(false);
38+
3639
private readonly SemaphoreSlim _connectionCreationSemaphore = new SemaphoreSlim(1);
3740
private bool _connectionHasFailed;
3841
private StreamConnection _physicalConnection;
@@ -89,7 +92,7 @@ protected override async Task<T> InvokeExportAsync<T>(NodeInvocationInfo invocat
8992
virtualConnection = _virtualConnectionClient.OpenVirtualConnection();
9093

9194
// Send request
92-
await WriteJsonLineAsync(virtualConnection, invocationInfo, cancellationToken);
95+
WriteJsonLine(virtualConnection, invocationInfo, cancellationToken);
9396

9497
// Determine what kind of response format is expected
9598
if (typeof(T) == typeof(Stream))
@@ -169,11 +172,20 @@ protected override void Dispose(bool disposing)
169172
base.Dispose(disposing);
170173
}
171174

172-
private static async Task WriteJsonLineAsync(Stream stream, object serializableObject, CancellationToken cancellationToken)
175+
private static void WriteJsonLine(Stream stream, object serializableObject, CancellationToken cancellationToken)
173176
{
174-
var json = JsonConvert.SerializeObject(serializableObject, jsonSerializerSettings);
175-
var bytes = Encoding.UTF8.GetBytes(json + '\n');
176-
await stream.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
177+
using (var streamWriter = new StreamWriter(stream, utf8EncodingWithoutBom, streamBufferSize, true))
178+
using (var jsonWriter = new JsonTextWriter(streamWriter))
179+
{
180+
jsonWriter.CloseOutput = false;
181+
182+
var serializer = JsonSerializer.Create(jsonSerializerSettings);
183+
serializer.Serialize(jsonWriter, serializableObject);
184+
jsonWriter.Flush();
185+
186+
streamWriter.WriteLine();
187+
streamWriter.Flush();
188+
}
177189
}
178190

179191
private static async Task<T> ReadJsonAsync<T>(Stream stream, CancellationToken cancellationToken)
@@ -184,7 +196,7 @@ private static async Task<T> ReadJsonAsync<T>(Stream stream, CancellationToken c
184196

185197
private static async Task<byte[]> ReadAllBytesAsync(Stream input, CancellationToken cancellationToken)
186198
{
187-
byte[] buffer = new byte[16 * 1024];
199+
byte[] buffer = new byte[streamBufferSize];
188200

189201
using (var ms = new MemoryStream())
190202
{

0 commit comments

Comments
 (0)