Search code examples
c#asynchronoussnmpsharp-snmp

Sharp SNMP Async method leaking stack memory


I'm trying the new 9.0.0 RC1 release of SharpSNMP for its async methods. It's easy to use - practically a drop-in replacement for the old synchronous method.

My code to poll a list of OIDs asynchronously is:

// create a new get request message
var message = new GetRequestMessage(Messenger.NextRequestId, VersionCode.V2, SNMPReadCommunity, oids);

// get a new socket
using (Socket udpSocket = SNMPManager.GetSocket())
{
    // wait for the response (this is async)
    var res = await message.GetResponseAsync(SNMPManager, new UserRegistry(), udpSocket);

    // check the variables we received
    CheckSnmpResults(res.Pdu().Variables);
}

I limit the number of OIDs per get-request to 25. My application connects to c.50 SNMP devices. Every 5 minutes a timer ticks and runs the above code several times in a loop in order to poll c.100 OIDs on each device. All good.

The problem is that the message.GetResponseAsync method is leaking memory. Every poll run adds 6 or 7 MB to my application's memory usage. Using the VS2015 memory profiler, I can see a large number of OverlappedData objects, each 65K, the number of which increases every time I run message.GetResponseAsync. So running this to receive c.200 SNMP get-requests every 5 minutes means my application's memory use quickly rockets.

Am I using message.GetResponseAsync incorrectly somehow? Is this a bug in SharpSNMPLib?

Thanks, Giles


Solution

  • A temp answer right now.

    The leak is caused by the fact that SocketAsyncEventArgs is not reused. This kind of object should be reused (as well as the Socket object) if a manager tries to manage an agent with multiple operations.

    The current design does not allow such reuse. Thus, an overall redesign is needed.

    I already have some ideas on how to move on, but probably it won't be able to make into 9.0 release. See if 9.5 can be the first release with the new design. And then I will go back and update this answer.

    Updated: this commit contains a quick fix to dispose the args object. But it does not enable reuse yet.