Question: When Is A Good Time To Call GC.Collect()?

0 comments suggest edit

Answer: When you don’t have enough change for the phone booth.

I’ll be here all week, thank you very much. Bad pun notwithstanding, the answer to this question is pretty much never (see Rico’s almost rule #1). The Garbage Collector in .NET is like a highly motivated and skilled employee. If you quit being a micro-manager (“You forgot to put the cover sheet on the TPS report”) and stop looking over its shoulder, it’s able to just do its job and perform quite well.

However, note that Rico says “Almost Rule #1”. That must mean there are appropriate exceptions to the rule, no matter how few they may be. What are those situations? The reason I ask is I ran into the following code on the net (dramatization):

/// 
/// Stops the socket server and closes 
/// every client connection.
/// 
public void Stop()
{
    if(_isDisposed)
        throw new ObjectDisposedException(
            "SocketServer", 
            "Object is already disposed.");

    CloseConnectedClients();
    CloseListener();

    GC.Collect();
    GC.WaitForPendingFinalizers();
}

This is the Stop() method of your typical Socket Server. It closes any connected socket clients and then closes the listening thread. After that, it calls GC.Collect() and GC.WaitForPendingFinalizers(), violating Rico’s almost rule. Is this perhaps one of those appropriate times to call GC.Collect()?

Typically, your socket server will have been running for a long time, so it is very likely it will have been promoted to Generation 2 and contain references to a several other Generation 2 objects. Rico points out that

If your algorithm is regularly producing objects that live to gen2 and then die shortly thereafter, you’re going to find that the percent time spent in GC goes way up. Forcing more of these collects is really the last thing you wanted to do (assuming you could, note again GC.Collect() doesn’t promise to do a gen2 collect).

However, this is situation is different in that the server has been around a while and calling Stop() on a server typically means you’re not planning to use the Server any time soon afterwards. In fact, you’re most likely about to dispose of it.

Given that, It seems to me that this might be one of those cases where calling GC.Collect() is appropriate. The goal here is a one time Generation 2 collection. Of course, there’s no guarantee that a Generation 2 collect will occur. Maybe this is a situation where it makes no difference either way. Any thoughts?

For more reading:\ Garbage Collector Basics and Performance Hints\ Programming For Garbage Collection

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

3 responses

  1. Avatar for Ian Griffiths
    Ian Griffiths August 15th, 2004

    You've constructed an argument for why it might possibly not be a really bad idea to call GC.Collect here. But I don't see any arguments as to why it might be a good idea.



    Looking at this code, it looks to me like someone put some code in a finalizer to do some tidying up somewhere, and wanted to force it to run at this point...



    One possible reason might be if the entire process is about to shut down. Usually the CLR gives up if all your finalizers don't manage to run within a few seconds at shutdown. Forcing a GC and then waiting for finalizers before exit would be a way of guaranteeing that all finalizers run before the process quits. (And if the process is about to shut down, most of the performance concerns probably aren't an issue any more...) So if this Stop method really is something done just before the process shuts down, then this might be the reason - it's about making sure finalizers run before the process exits.



    Or it might just be totally misguided...



    In general, forcing an early GC tends to promote objects that might not otherwise have got promoted which, as Rico has thoroughly documented, is a Bad Thing. You wouldn't want that to occur on a regular basis.

  2. Avatar for xx
    xx July 30th, 2007

    Imports System
    Namespace GCCollect_Example
    Class MyGCCollectClass
    Private Const maxGarbage As Integer = 1000
    Shared Sub Main()
    'Put some objects in memory.
    MyGCCollectClass.MakeSomeGarbage()
    Console.WriteLine("Memory used before collection: {0}", GC.GetTotalMemory(False))
    'Collect all generations of memory.
    GC.Collect()
    Console.WriteLine("Memory used after full collection: {0}", GC.GetTotalMemory(True))
    End Sub
    Shared Sub MakeSomeGarbage()
    Dim vt As Version
    Dim i As Integer
    For i = 0 To maxGarbage - 1
    'Create objects and release them to fill up memory
    'with unused objects.
    vt = New Version()
    Next i
    End Sub
    End Class
    End Namespace

  3. Avatar for Ali
    Ali September 17th, 2008

    Dear sir i am working on vb.net application , when i close my application a thread is running in my task manager even when i close my application . i have builten close button for closing my application . i close my application with that cross button beside form maximize option. I have also fire form closing event and write me.dispose() and then me.close() even than my application thread keep running in my task manager . Kindly help to resolve this issue i need to break that running project thread from task manager.
    reagards