Search code examples
c#.netwindowsmemory-leaksnetmq

AsyncIO.ForceDotNet.Force() causes memory leak on Windows XP


Environment

  • OS in Production: Windows XP SP3
  • IDE: Microsoft Visual Studio 2013 Ultimate Edition
  • Targeted framework: .NET framework 3.5
  • NetMQ: 3.3.1
  • AsyncIO: 0.1.18
  • Language: C#

We have a need to run a NetMQ application using a simple REQ REP socket on Windows XP SP3. We learned from Issue #412 that when running on Windows XP, that we need to call AsyncIO.ForceDotNet.Force(); prior to using NetMQ.

What we find after we start running our application for a while (~ 3 minutes), since we send a high number of messages per second (1 message per 5 milliseconds or 12,000 messages per second), we see memory leak at the rate of ~ 3MB / sec. Our production machine only has 1 GB of RAM and soon causes our application to crash.

The code below reproduces the leak quite well. To see the leak, you can run it on any Windows OS (7, 8, or 10); Windows XP SP3 is not required (but without AsyncIO.ForceDotNet.Force(), NetMQ cannot be run on Windows XP SP3).

Client code (the problematic code that prevents us from deploying the application in production)

class Client
{
    static void Main(string[] args)
    {
        AsyncIO.ForceDotNet.Force();
        while (true)
        {
            using (RequestSocket request = new RequestSocket())
            {
                request.Connect("tcp://127.0.0.1:5555");
                request.SendFrame("Hello");
                byte[] recData;
                bool result = request.TryReceiveFrameBytes(TimeSpan.FromSeconds(1), out recData);
                if (result)
                    Console.WriteLine(string.Format("Reply From Server:{0}", System.Text.Encoding.Default.GetString(recData)));
                System.Threading.Thread.Sleep(5);
            }
        }
    }
}

Corresponding Server Code (which leaks as well)

class Server
{
    static void Main(string[] args)
    {
        AsyncIO.ForceDotNet.Force();
        using (ResponseSocket response = new ResponseSocket())
        {
            response.Bind("tcp://127.0.0.1:5555");                
            while (true)
            {
                byte[] recData = response.ReceiveFrameBytes();
                Console.WriteLine(string.Format("Reply From Server:{0}", System.Text.Encoding.Default.GetString(recData)));
                response.SendFrame("World");
                System.Threading.Thread.Sleep(1);
            }                
        } 
    }
}

Memory Profile of client application


Solution

  • Just pushed following commit to AsyncIO, check it out, if it solve your problem I will release a new version to nuget.

    https://github.com/somdoron/AsyncIO/commit/b7100a54ec55d3b3fdb9334d1f46a2ec5a070c0a