Best Practice For Forcing Garbage Collection in C#

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

Garbage Collection best practice in .net

System.GC.Collect is called when all objects which are there in memory are to be collected by the Garbage Collector. Objects which are referenced in managed code are not considered for Garbage collection. This method is used to force the system to reclaim the available memory.

Dispose() is not part of GC but as better practice you can use this. It should only be used for objects which uses unmanaged resources like FileStream etc. It should release all the resources that it owns. When you know that certain resources will not be released by GC then you can use the Dispose() method.

The using statement ensures the correct use of IDisposable objects.

On a side note: The GC does not call Dispose, it calls the finalizer(which you should call from Dispose(false))

Also, to make ensure that resources are always released appropriately, a Dispose method should be callable multiple times without throwing an exception.


MSDN says:

"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. "

Check this blog:-

GC.Collect() asks the system to perform a collection "now". You
shouldn't mess with this; the system usually has a much better idea
than you do of when collection is necessary.

So is the best practice:

You can use the using block or as you mentioned use the Dispose method.

Why should you use IDisposable and Dispose?

MSDN says

In many cases it is possible for objects that would otherwise always
need to be finalized to avoid that cost by implementing the
IDisposable interface. This interface provides an alternative method
for reclaiming resources whose lifetime is well known to the
programmer, and that actually happens quite a bit. Of course it's
better still if your objects simply use only memory and therefore
require no finalization or disposing at all; but if finalization is
necessary and there are many cases where explicit management of your
objects is easy and practical, then implementing the IDisposable
interface is a great way to avoid, or at least reduce, finalization
costs.

Also check this article on Improve garbage collector performance using finalize/dispose pattern

Is it a good idea to force garbage collection to be sure that GC won't check quite large objects later?

OK look, garbage collection is still just a heuristic, it's trying to do the best guess it can in general, but it may be possible that you have a legitimate claim at knowing better than it at particular times.

Take for example a game with a lot of assets. When you switch to a new zone, you pop up a loading screen and start loading your new data, releasing references to the old data. It won't get collected yet because you haven't hit your threshold, but you might hit it soon as you're starting to create your little matrices every frame to present your game, and then you'll get a (possibly noticeable) stutter as you're unloading hundreds of megs of data and moving everything else around to compact the queues.

Now you can instead force a collect after the new assets were loaded, since the user is already in "idle" mode, staring at your progress bar, he won't notice the little stutter and your game will seem smoother overall afterwards.

The real trick then becomes knowing when to interfere and when not to. When in doubt, don't -- that collection will happen regardless, and making it happen more often will only make your application seem more stuttery. You need something to "hide" it, like a long task that locks your application with a progress bar that somehow generates a lot of finalized objects -- really a game loading screen is the only thing I can come up with, but YMMV.

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

Efficient Garbage Collection


does that mean the memory will get freed from ObjectD as soon as I set
it to null?

It's not object sets to null - its reference to object in memory sets to null. And object will exist until Garbage Collector will collect it (if you don't have any other references to this object).

Take a look on Fundamentals of Garbage Collection

When is it advisable to control the garbage collection under C#

The code is good; but for the wrong reasons (sort of).


I've been told to use the automatic garbage collection

Somewhat facetiously, you don't need to explicitly use the automatic garbage collection. Because it's automatic.


using blocks are used for disposing objects (which implement the IDisposable interface).

The intention (lowering memory usage) is the same here. Many disposable objects free their data; so that the automatic garbage collector is allowed to clean it when it wants to.


As a very minor comment, you can reduce nesting by omitting the brackets of the top using statement:

using (SqlDataAdapter da = new SqlDataAdapter(cmdstring, con))
using (DataTable dt = new DataTable())
{
da.Fill(dt);

if (dt.Rows.Count != 0)
{
splitlst.Add(dt.Rows[0][0].ToString());//kunde
splitlst.Add(dt.Rows[0][1].ToString());
splitlst.Add(dt.Rows[0][2].ToString());
splitlst.Add(dt.Rows[0][3].ToString());
splitlst.Add(dt.Rows[0][4].ToString());
splitlst.Add(dt.Rows[0][5].ToString());
}
}

Similar to other code blocks (if, foreach, ...), the braces are not necessary for a single line of code.

Technically, you'd still need to indent. Similar to doing:

if(1 + 1 != 2) 
BurnMathBooks(); //still indented

You should technically also do:

using (SqlDataAdapter da = new SqlDataAdapter(cmdstring, con))
using (DataTable dt = new DataTable()) //still indented
{
//...
}

But since the lack of indentation doesn't actually make the code more unreadable; it's acceptable to omit it in this case.

using (SqlDataAdapter da = new SqlDataAdapter(cmdstring, con))
using (DataTable dt = new DataTable())
{
//...
}

How to force garbage collector to run?

System.GC.Collect() forces garbage collector to run. This is not recommended but can be used if situations arise.

NUnit OneTimeTearDown Garbage collection best practice

You should dispose of any disposable external resources, which you acquire. Where you do this depends on where you acquire the resource.

  1. If you acquire it in your test fixture constructor, then let NUnit dispose of it. You do that by having the fixture class implement IDispose.

  2. If you acquire it in a OneTimeSetUp, then dispose of it in the corresponding OneTimeTearDown.

  3. If you acquire it in a SetUp, then dispose of it in the corresponding TearDown.

  4. If you acuire it in a TestMethod, then dispose of it before that method returns. The simplest way to do this is via using.

All that said and explained, your example doesn't seem to acquire any disposable external resources. So I would not do any of those things. :-)

Generally, the time people spend figuring out overly complicated code outweighs any small advantage in efficiency. So wait till you see a performance problem before you fix it.

Undesirable Garbage Collection

I run a recipe related website, and I store a massive graph of recipes and their ingredient usage in memory. Due to the way I pivot this information for quick access, I have to load several gigs of data into memory when the application loads before I can organize the data into a very optimized graph. I create a huge amount of tiny objects on the heap that, once the graph is built, become unreachable.

This is all done when the web application loads, and probably takes 4-5 seconds to do. After I do so, I call GC.Collect(); because I'd rather re-claim all that memory now rather than potentially block all threads during an incoming HTTP request while the garbage collector is freaking out cleaning up all these short lived objects. I also figure it's better to clean up now since the heap is probably less fragmented at this time, since my app hasn't really done anything else so far. Delaying this might result in many more objects being created, and the heap needing to be compressed more when GC runs automatically.

Other than that, in my 12 years of .NET programming, I've never come across a situation where I wanted to force the garbage collector to run.



Related Topics



Leave a reply



Submit