Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory Issue with async socket and begin Send

I noticed the today that my one application im developing is seriously growing in memory. So I did a Visual Studio Memory Profile and I found the following results:

 Function Name  Inclusive Allocations   Exclusive Allocations   Inclusive Bytes Exclusive Bytes
 System.Net.Sockets.Socket.BeginSend(uint8[],int32,int32,valuetype System.Net.Sockets.SocketFlags,valuetype System.Net.Sockets.SocketError&,class System.AsyncCallback,object)  3 192 569   3 192 561   635 307 885 635 307 621

This was on top of the memory Usage with ~600Meg

This doesnt seem correct to me and im Not sure why it is so?

Here is my send function:

private void SendSignal(Byte[] signal)
    {
        if (state.WorkSocket.Connected)
        {
            try
            {
                state.WorkSocket.BeginSend(signal, 0, signal.Length, 0, new AsyncCallback(SendCallback), state.WorkSocket);
            }
            catch (Exception e)
            {                    
                log.Error("Transmission Failier for ip: " + state.WorkSocket.AddressFamily , e);
            }
        }
        else
        {
            CloseConnection();
        }
    }

The application blocks on a concurrent QUEUE with messages to send, And when it successfully dequeues a message it loops through all the registered (Clients) and sends this message to them.

Am I using the begin-send Incorrectly?

One thing I though of, is the fact that its being async, might my program loop through the entire queue and offload it all into the async system buffer?

{EDIT}

private void SendCallback(IAsyncResult asyncResult)
    {
        try
        {
            Socket handler = (Socket)asyncResult.AsyncState;
            int bytesSent = handler.EndSend(asyncResult);
            if (bytesSent == 0)
            {
                CloseConnection();
                return;
            }
        }
        catch
        {
            CloseConnection();
        }
    }

Way I drain the queue

ExponentialBackoff eb = new ExponentialBackoff();
        while (run)
        {
            //Fetch Latest Item
            ILogItem logItem;
            if (incomingQueue.TryDequeue(out logItem))
            {
                //Handle the logItem
                SendEventToObservers(logItem);
                //Reset the exponetial backoff counter
                eb.reset();
            }
            else
            {
                //Exponential backoff thread sleep
                eb.sleep();
            }
        }

private void SendEventToObservers(ILogItem item)
    {
        foreach (var observer in registeredObservers.ToList())
        {
            if (observer != null)
            {
                observer.OnMessageRecieveEvent(new ObserverEvent(item));
                // This just calls private void SendSignal(Byte[] signal)
            }
        }
    }
like image 777
Zapnologica Avatar asked Nov 11 '22 04:11

Zapnologica


1 Answers

For each queue item you issue an asynchronous send. This means that an unbounded number of send operations might be pending. Resource usage is unbounded. Usually, you'd issue a send and only issue the next after the previous one has completed.

With async IO this is not that easy to do. Either switch to using await (which turns it back into an easy problem) or just use synchronous IO.

like image 73
usr Avatar answered Nov 14 '22 21:11

usr