.NET Array Dictionary List String 2D Async DataTable Dates DateTime Enum File For Foreach Format IEnumerable If IndexOf Lambda LINQ Parse Path Process Property Regex Replace Sort Split Static StringBuilder Substring Switch Tuple


C#: .NET
Garbage collection: GC

GC.Collect. The C# language is a garbage-collected language. This means that memory that is no longer referenced by your program will be reclaimed and is later reused. With GC.Collect, we force a garbage collection to occur at any time.


Method

Example. First, this example invokes the GC.Collect method. Three calls to get the total memory usage on the system are present. They occur before the allocation, after the allocation, and after the forced garbage collection.

Tip: You can see that memory returns to its low level after the garbage collection.

Based on:

.NET 4.5

C# program that uses GC.Collect

using System;

class Program
{
    static void Main()
    {
	long mem1 = GC.GetTotalMemory(false);
	{
	    // Allocate an array and make it unreachable.
	    int[] values = new int[50000];
	    values = null;
	}
	long mem2 = GC.GetTotalMemory(false);
	{
	    // Collect garbage.
	    GC.Collect();
	}
	long mem3 = GC.GetTotalMemory(false);
	{
	    Console.WriteLine(mem1);
	    Console.WriteLine(mem2);
	    Console.WriteLine(mem3);
	}
    }
}

Output

45664
245696
33244

Question

Discussion. So when should you call the GC.Collect method in your .NET programs? In my experience, you should never call it. The call will usually not do much to reduce overall memory usage. And it will impose a slowdown whenever it is called.

In ASP.NET: The GC.Collect on one application will cause a performance hit on all web sites in the same pool.

Framework: NET

This method adds more complexity to your program and probably even reduces overall performance. The .NET garbage collector is finely tuned by Microsoft. They have more time and money to spend on tweaking its performance than you do.

And: I have used GC.Collect (without success) in attempts to improve performance, particularly after a lot of allocations after startup.


Pound symbol

CollectionCount. GC.CollectionCount returns an int. It tells us how many times garbage collection has occurred. Getting information about how often garbage collection is occurring in your program is not always simple.

Tip: With CollectionCount and the GC.MaxGeneration property, we get this information.

Note: Because most objects die young, generations are used to optimize which elements are scanned.

And: Newer objects are scanned more often because they are most likely to have become dead.

Compiler
C# program that uses CollectionCount

using System;

class Program
{
    static void Main()
    {
	// This loop does a lot of allocations!
	for (int i = 0; i < 100; i++)
	{
	    for (int a = 0; a < 1000; a++)
	    {
		System.IO.Path.GetRandomFileName();
		System.IO.Path.GetRandomFileName();
	    }
	    System.Threading.Thread.Sleep(1);
	}

	// Display collection counts.
	for (int i = 0; i <= GC.MaxGeneration; i++)
	{
	    int count = GC.CollectionCount(i);
	    Console.WriteLine(count);
	}
    }
}

Output

15
0
0
Note

Program output. On my computer, the program resulted in 15 generation 0 garbage collections. This is because the memory allocations caused by GetRandomFileName were all put in generation 0.

Then: They died, meaning they lost any reference from the program's flow graph. As is sadly the typical case, these objects died young.

Path.GetRandomFileName
Garbage collection: GC

GetTotalMemory. GC.GetTotalMemory returns the number of bytes allocated. It accesses statistics about the managed heap. It returns data about the entire .NET Framework, not the specific program. With it we determine the sizes of objects in memory.

Parameter: The method receives one parameter of type bool, which lets you demand a garbage collection to occur before taking the numbers.

Bool

Next: This program shows the memory difference after allocating ten million bytes and then collecting them.

C# program that uses GC

using System;

class Program
{
    static void Main()
    {
	long bytes1 = GC.GetTotalMemory(false); // Get memory in bytes

	byte[] memory = new byte[1000 * 1000 * 10]; // Ten million bytes
	memory[0] = 1; // Set memory (prevent allocation from being optimized out)

	long bytes2 = GC.GetTotalMemory(false); // Get memory
	long bytes3 = GC.GetTotalMemory(true); // Get memory

	Console.WriteLine(bytes1);
	Console.WriteLine(bytes2);
	Console.WriteLine(bytes2 - bytes1); // Write difference
	Console.WriteLine(bytes3);
	Console.WriteLine(bytes3 - bytes2); // Write difference
	Console.ReadLine();
    }
}

Output

21060           Program started with these bytes.
10021092        After ten million bytes allocated.
10000032        Difference.
12860           After garbage collection.
-10008232       Difference.

In this example, the calls to GC.GetTotalMemory receive a single parameter in this program, either false or true. The literal false is the default here. It indicates that an expensive collection should not be forced.

FalseProgramming tip

Usually: Forcing a GC has no benefit in programs. It just adds to the complexity. It is best to leave this parameter as false.


ASPNET web programming framework

Managed heaps. The GC.GetTotalMemory method operates on the concept of the managed heap, not the program that you are calling it from. Programs that allocate data on the managed heap are called mutators. One managed heap can have many mutators.

Note: When you invoke GC.GetTotalMemory, you will be counting the allocations from all the mutator programs.

And: On a web server, this would add allocations from other programs also running in ASP.NET.


Program

Statistics. There is an excellent way of getting a general feel of the amount of memory your program is allocating on the managed heap. You can set up a special web page or dialog in your program that reports the statistics from GetTotalMemory.

It can store the previous figure in a static field, and then subtract the second from the first to see the change. This does not give you precise and exact figures. But it helps you determine if memory is or will become a problem.


C# programming language

Summary. The GC.Collect method is best used for diagnostics purposes (like determining a base line of memory usage). You can also use it to see if all the objects you no longer need are not reachable and can be collected by the garbage collector.

However: In deployment, the GC.Collect method is not useful because it often has little benefit and might even reduce performance.