feat: use a shared memory pool for reading
This commit is contained in:
parent
1c5a3870c2
commit
1dbc60ba7c
|
@ -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);
|
||||
|
||||
try {
|
||||
WebSocketReceiveResult result;
|
||||
var i = 0;
|
||||
do {
|
||||
result = await client.ReceiveAsync(buffer, CancellationToken.None);
|
||||
bytes.AddRange(buffer[..result.Count]);
|
||||
result = await client.ReceiveAsync(bytes[i..maxSize], CancellationToken.None);
|
||||
i += result.Count;
|
||||
|
||||
// 1 MiB
|
||||
if (bytes.Count > 1_048_576) {
|
||||
throw new Exception();
|
||||
// break if we've filled up the buffer, even if message isn't complete
|
||||
if (i == maxSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > maxSize) {
|
||||
throw new Exception("read too many bytes for one message");
|
||||
}
|
||||
} while (!result.EndOfMessage);
|
||||
|
||||
return MessagePackSerializer.Deserialize<ResponseContainer>(bytes.ToArray());
|
||||
return MessagePackSerializer.Deserialize<ResponseContainer>(bytes);
|
||||
} finally {
|
||||
ArrayPool<byte>.Shared.Return(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user