I am creating a lib to listen to server notifications (more than 100,000 requests per hour), when using WebSocketSharp it is receiving all 100,000 notifications but there is memory leak (server goes out of memory after couple of hours).
When using System.Net.WebSockets, the memory cleared correctly (no memory leak) but I only receive 60,000 notifications (some messages are missing). I am using the function below to receive the notification (changing options and buffer didn't help):
async Task Receive()
{
Task RunningTask = Task.Factory.StartNew(async () =>
{
await HandleMessage(channel.Reader);
});
while (WebSocket.State == WebSocketState.Open)
{
try
{
//var buffer = new byte[256];
var maxSize = BufferSize;
var framePayload = new Memory<byte>(new byte[maxSize]);
var buffer = new Memory<byte>(new byte[maxSize / 2]);
ValueWebSocketReceiveResult result;
DateTime receiveTime = DateTime.Now;
int framePayloadSize = 0;
do
{
result = await WebSocket.ReceiveAsync(buffer, CancellationToken.None);
receiveTime = DateTime.Now;
var data = buffer.Slice(0, result.Count);
if (framePayloadSize + result.Count > maxSize)
{
var tempFramePayload = new Memory<byte>(new byte[maxSize]);
framePayload.CopyTo(tempFramePayload);
maxSize *= 2;
framePayload = new Memory<byte>(new byte[maxSize]);
tempFramePayload.CopyTo(framePayload);
}
data.CopyTo(framePayload.Slice(framePayloadSize, result.Count));
framePayloadSize += result.Count;
} while (!result.EndOfMessage);
if (result.Count != 0)
{
try
{
if (result.MessageType == WebSocketMessageType.Close)
{
_log.LogInformation("DotNetWS Message Close.");
await WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None);
channel.Writer.Complete();
}
else
{
await channel.Writer.WriteAsync(new() { Payload = framePayload, PayloadSize = framePayloadSize });
}
}
catch (Exception ex)
{
_log.LogError("DotNetWS Error: {ErrorMessage}", ex.Message);
}
}
}
catch (Exception e)
{
_log.LogError("DotNetWS Error: {ErrorMessage}", e.Message);
}
}
_log.LogInformation("DotNetWS Channel is closed");
}
Here is the Webscoketsharp doing the same thing, it is working fine (except for the memory leak part).
WebSocket = new WebSocket(uri);
WebSocket.OnMessage += delegate (object sender, MessageEventArgs e)
{
try
{
NotificationData<JObject> notificationData = JsonConvert.DeserializeObject<GCPayload>(e.Data);
.......
}
catch (Exception value)
{
Console.WriteLine(value);
}
};
tempFramePayloaddirectly toframePayloadafter the first copy instead of allocating and copying again.channel? How is it declared and initialized?System.Threading.Channels.Channel<GCPayload> channel = System.Threading.Channels.Channel.CreateUnbounded<GCPayload>( new System.Threading.Channels.UnboundedChannelOptions { SingleWriter = false, SingleReader = false, AllowSynchronousContinuations = true });