Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Something blocks my memory and the program hangs on GC.Collect() or GC.GetTotalAmountOfMemory(true)

whenever I call a GC.Collect() or GC.GetTotalAmountOfMemory(true) the whole program just hangs. Now, I know what you gonna say: Don't call GC.Collect() the GC takes care of itself. The problem is: It doesn't in my case, something hangs around in memory and the GC can't get rid of it.

I've no idea what it could be (project is big/old). I hope someone knows how to obtain informations about what the GC tries to do (and obviously can't do) so that I can search for the problem or if something like a memory profiler could be of any help here (I've ANTS currently installed) and what I should search for.

*edit something I totally forgot: Sometimes when I call one of the two methods of GC, the memory usage increases by ~10 kilobytes / second

*edit2 I've to correct myself: GC.Collect() runs just fine. Only GC.GetTotalMemory(true) hangs. GC.GetTotalMemory(false) works just fine, too.

*edit3 and yup as some of you already said: It seems to be a finalizer somewhere. When I run WaitForPendingFinalizers() it just sits there, doing nothing aswell.

ok, now I'm completely confused: When I enter a GC.GetTotalMemor(true) or a GC.WaitForPendingFinalizers() into the immediate window of Visual Studio after I paused the debugger, the program hangs (that's what I did the whole time...I feel stupid now). When I add it to my usual source code and compile it, it works just fine.

Sorry about the whole fuzz, seems the memoryleak has another cause.

like image 439
Steffen Winkler Avatar asked Mar 14 '12 11:03

Steffen Winkler


2 Answers

Do you override any finalizers? When a finalizer is not returning ( Maybe you are waiting at any point for another thread ) the application may hang. The GC.Collect() invokes the finalizer but its never returning since it waits for a finalizer to return. This may be also the cause for your memory leak because the GC cannot finish the garbage collection.

Solution

You should be able to debug it, when the GC is collecting and you press "pause" it should show you the stack trace where it hangs. If everything goes wrong you maybe need to check the disassembly where your application is hanging.

GetTotalMemory(true)

This method forces the garbage collection, so it's the same like GC.Collect().

Update

Lets take a look at GetTotalMemory:

public static long GetTotalMemory(bool forceFullCollection)
{
    long totalMemory = GC.GetTotalMemory();
    if (!forceFullCollection)
    {
        return totalMemory;
    }
    int remainingSteps = 20;
    long lastMemory = totalMemory;
    float num4;
    do
    {
        GC.WaitForPendingFinalizers();
        GC.Collect();
        totalMemory = lastMemory;
        lastMemory = GC.GetTotalMemory();
        num4 = (float)(lastMemory - totalMemory) / (float)totalMemory;
    }
    while (remainingSteps-- > 0 && (-0.05 >= (double)num4 || (double)num4 >= 0.05));
    
    return lastMemory;
}

As you can see that GetTotalMemory is waiting for finalizers, so it has to be a finalizer which hangs up the application. GC.Collect() is called when the finalizers are finished and will never be called because it never passes the line before.

At any point in your application ( unsafe code? another thread? ) there is something which allocates a lot of memory while the GC never has the chance to clean up existing memory.

Disclaimer

This is a pure guess, i don't know if the GC handles such situations but i think it cannot break the execution of a finalizer because it may take a long time and the GC doesn't know if he is just hanging or still finalizing.

like image 143
Felix K. Avatar answered Oct 08 '22 03:10

Felix K.


Have you considered to use the server mode GC settings, so that one GC thread runs per processor core?
Have you investigated the issue using performance counters, dumps or profilers? ANTS Memory profiler is very helpful if the application itself does not get slowed too much by the use of it.
I would also look at your application using Windows Process Explorer to get a taste what is happening on the memory side.

like image 43
weismat Avatar answered Oct 08 '22 03:10

weismat