Search code examples
c#.net.net-4.0memory-leaksworkflow-foundation-4

Crazy memory leak with WorkflowInvoker while debugging


EDIT: It seems my question suffers from TL;DR syndrome. So instead of reading the question, you may opt to see a video I've found demonstrating the issue: http://www.youtube.com/watch?v=xD0mRWJazis. Not shown in the video: it only happens while the debugger is attached.


I have an application that uses the WorkflowInvoker from Windows Workflow Foundation 4.0. It seems that while the Visual Studio 2010 debugger is attached to the process, each time I call WorkflowInvoker.Invoke(...) the process size grows by about 440 KB, until the process grows to a few gigabytes and my computer runs out of memory leading to the application freezing and the debugger crashing (my application only takes a minute or so to get there). When the debugger is not attached, no memory leaks occur.

Visual Studio 2010 status bar showing "Loading symbols for Workflow..."

As shown in the screenshot above, every time a workflow is invoked, Visual Studio's status bar shows Loading symbols for Workflow... even though it executes the same workflow. I'm guessing this has something to do with the memory leak. I tried disabling symbol loading by going to Tools > Options > Debugging > Symbols and under Automatically load symbols for I selected Only specified modules and made sure there are no modules specified. This did not help, the process size still grew steadily and Visual Studio still loaded workflow symbols.

Below is the minimal code to repro the issue. Look at Task Manager while running it with and without a debugger (careful, it'll eat up memory very quickly when debugging!):

var workflow = new WorkflowInvoker(new Sequence());

while (true)
    workflow.Invoke();   ////  Memory leak!  //// 

A more expanded console program demonstrating the issue while displaying memory consumption is included below. It only runs at about 100 empty workflows per second. Try running it without debugging (Ctrl+F5) and compare it to running it with debugging (F5). You'll see the difference immediately. If you'd rather not run the sample, I included the results as screenshots below.

using System;
using System.Activities;
using System.Activities.Statements;
using System.Diagnostics;
using System.Threading;

class Program
{
    static Timer Timer = new Timer(PrintMemory, null, 1000, 1000);
    static double PreviousSize;

    static void Main(string[] args)
    {
        Console.WriteLine("Debugger {0} attached.",
            Debugger.IsAttached ? "IS" : "is NOT");

        var workflow = new WorkflowInvoker(new Sequence());

        while (true)
        {
            workflow.Invoke();   ////  Memory leak!  ////
            Thread.Sleep(10);
        }
    }

    static void PrintMemory(object o)
    {
        double newSize = Process.GetCurrentProcess().PrivateMemorySize64 / 1048576d;
        Console.WriteLine("Grew by {0,5:F2} MB (total {1,7:F2} MB)",
            newSize - PreviousSize, newSize);
        PreviousSize = newSize;
    }
}

Here's a 30-second run of the program without and with debugging:

The included sample application running for 30 seconds without a debugger on the left, showing a steady memory footprint of 33 MB, and with a debugger on the right showing a memory footprint growing by 43 MB each second, reaching 1.6 GB after only 30 seconds.

As you can see, the memory grows by around 43 MB every seconds. I must be able to run my application under the debugger. Any suggestions?

EDIT: I've opened a Connect bug for this issue here.

EDIT: Well that was a bust. Apparently Connect is only for the latest and greatest. VS2012 has RTMed a whole ten minutes ago but connect isn't accepting any feedback for VS2010 anymore. My next stop: a post on the WF4 forum. Fingers crossed.


Solution

  • As Tim Lovell-Smith correctly noted in the MSDN Forums question I posted, this is a known bug in .NET 4.0 which was fixed in .NET 4.5. Fortunately, simply installing .NET 4.5 fixes the issue for Visual Studio 2010 as well.