feat: use a shared memory pool for reading

This commit is contained in:
Anna 2022-07-31 19:47:23 -04:00
parent 1c5a3870c2
commit 1dbc60ba7c
1 changed files with 24 additions and 13 deletions

View File

@ -1,4 +1,5 @@
using System.Net.WebSockets;
using System.Buffers;
using System.Net.WebSockets;
using ExtraChat.Protocol;
using MessagePack;
@ -16,20 +17,30 @@ public static class Ext {
}
public static async Task<ResponseContainer> ReceiveMessage(this ClientWebSocket client) {
var bytes = new List<byte>(2048);
var buffer = new ArraySegment<byte>(new byte[2048]);
const int maxSize = 1_048_576;
// rent a 1 MiB byte array from the shared runtime pool
var bytes = ArrayPool<byte>.Shared.Rent(maxSize);
WebSocketReceiveResult result;
do {
result = await client.ReceiveAsync(buffer, CancellationToken.None);
bytes.AddRange(buffer[..result.Count]);
try {
WebSocketReceiveResult result;
var i = 0;
do {
result = await client.ReceiveAsync(bytes[i..maxSize], CancellationToken.None);
i += result.Count;
// 1 MiB
if (bytes.Count > 1_048_576) {
throw new Exception();
}
} while (!result.EndOfMessage);
// break if we've filled up the buffer, even if message isn't complete
if (i == maxSize) {
break;
}
return MessagePackSerializer.Deserialize<ResponseContainer>(bytes.ToArray());
if (i > maxSize) {
throw new Exception("read too many bytes for one message");
}
} while (!result.EndOfMessage);
return MessagePackSerializer.Deserialize<ResponseContainer>(bytes);
} finally {
ArrayPool<byte>.Shared.Return(bytes);
}
}
}