When Is It Acceptable to Call Gc.Collect

When is it acceptable to call GC.Collect?

If you have good reason to believe that a significant set of objects - particularly those you suspect to be in generations 1 and 2 - are now eligible for garbage collection, and that now would be an appropriate time to collect in terms of the small performance hit.

A good example of this is if you've just closed a large form. You know that all the UI controls can now be garbage collected, and a very short pause as the form is closed probably won't be noticeable to the user.

UPDATE 2.7.2018

As of .NET 4.5 - there is GCLatencyMode.LowLatency and GCLatencyMode.SustainedLowLatency. When entering and leaving either of these modes, it is recommended that you force a full GC with GC.Collect(2, GCCollectionMode.Forced).

As of .NET 4.6 - there is the GC.TryStartNoGCRegion method (used to set the read-only value GCLatencyMode.NoGCRegion). This can itself, perform a full blocking garbage collection in an attempt to free enough memory, but given we are disallowing GC for a period, I would argue it is also a good idea to perform full GC before and after.

Source: Microsoft engineer Ben Watson's: Writing High-Performance .NET Code, 2nd Ed. 2018.

See:

  • https://msdn.microsoft.com/en-us/library/system.runtime.gclatencymode(v=vs.110).aspx
  • https://msdn.microsoft.com/en-us/library/dn906204(v=vs.110).aspx

Should i call GC.Collect

Short answer: No.

If you call GC.Collect(), you probably have a problem. It is exceedingly rare to need to call this.

In your current example, it will not help given the current code. Unless you physically clear the list of Message objects, they will not be garbage collected because the caller still has references to the objects in that List<T> instance.

Of course that advice is based on the assumption that no other references exist to each Message object.

You could potentially add some more determinism to your process by removing the message objects from the List<T> once they have been processed, or by switching to a data structure which embodies this principle inherently such as a Queue<T> or Stack<T> depending on your ordering requirements.

public int SendMultipleMessages(Queue<Message> messages)
{
while (messages.Count > 0)
{
var message = messages.Dequeue();
// do something with message, and once you're done it is
// probably eligible for garbage collection because it is
// no longer in the Queue
}

Task.Factory.StartNew(() =>
{
//very time demanding task
_sendRequestHandler.SendMultipleMessages(BatchId);
});

return BatchId;
}

c# correct way to call GC.Collect

C# is a Garbage Collected language. The Garbage Collector allocates resources for you, and reclaims them when they are no longer used.

Unless you have a really good reason, you shouldn't be calling GC.Collect() at all - the Garbage Collector is smart, and will only run when it thinks it needs to.

This can be triggered by a number of situations, as shown in the docs:

Garbage collection occurs when one of the following conditions is true:

  • The system has low physical memory. This is detected by either the low memory notification from the OS or low memory indicated by the host.

  • The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.

  • The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.

Importantly, Garbage Collection can cause all running threads to be paused so it can analyze all the objects in your heap to see if they're still needed at all. This takes time, and if you're running it frequently when it's not required, it can negatively affect the performance of your program.

Best Practice for Forcing Garbage Collection in C#

The best practise is to not force a garbage collection.

According to MSDN:

"It is possible to force garbage
collection by calling Collect, but
most of the time, this should be
avoided because it may create
performance issues. "

However, if you can reliably test your code to confirm that calling Collect() won't have a negative impact then go ahead...

Just try to make sure objects are cleaned up when you no longer need them. If you have custom objects, look at using the "using statement" and the IDisposable interface.

This link has some good practical advice with regards to freeing up memory / garbage collection etc:

http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

Under what circumstances, we need to call GC.Collect twice

Sounds like you have something with a finalizer, basically - if you only call GC.Collect() once, the finalizers are finishing but the finalized objects aren't being collected.

Whether or not that represents a bug is a different matter. Generally it's not a good idea for there to be finalizers which actually need to be executing, but maybe it's okay in your case.

Should I call GC.Collect() in Dispose() method?

The dispose never called Garbage Collector automatically, the dispose design to free un-managed resource. The Garbage Collector execution is scheduled processes which will run in after specified time.

When you call .Net Garbage Collector, it calls the Object.Finalize method of an object on garbage collection to free manage resource, that's why your memory use count show less number

Does Calling GC.Collect() Do Garbage Collection On Only Your Process or All Processes?

Only your process. The .Net runtime is instantiated in your own process, so you only control your own .Net internals.



Related Topics



Leave a reply



Submit