TheDeveloperBlog.com

Home | Contact Us

C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML

C# GC.Collect Examples: CollectionCount, GetTotalMemory

This C# example program demonstrates the GC.Collect method. It forces a garbage collection.

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.

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

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.

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.

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

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

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.

False

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

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.

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.

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.


Related Links

Adjectives Ado Ai Android Angular Antonyms Apache Articles Asp Autocad Automata Aws Azure Basic Binary Bitcoin Blockchain C Cassandra Change Coa Computer Control Cpp Create Creating C-Sharp Cyber Daa Data Dbms Deletion Devops Difference Discrete Es6 Ethical Examples Features Firebase Flutter Fs Git Go Hbase History Hive Hiveql How Html Idioms Insertion Installing Ios Java Joomla Js Kafka Kali Laravel Logical Machine Matlab Matrix Mongodb Mysql One Opencv Oracle Ordering Os Pandas Php Pig Pl Postgresql Powershell Prepositions Program Python React Ruby Scala Selecting Selenium Sentence Seo Sharepoint Software Spellings Spotting Spring Sql Sqlite Sqoop Svn Swift Synonyms Talend Testng Types Uml Unity Vbnet Verbal Webdriver What Wpf