C# Garbage Collection

    1 Votes

In the .Net Framework garbage collector manages the allocation of memory and release the memory of the application. Every time when the new object is created the common language runtime allocates the memory from the managed heap and as long as the address space is available in the managed heap, the runtime continues to allocate the space for new objects.

As memory is not unlimited so the garbage collector performs a collection in order to free some memory. The garbage collector performs a collection which checks for objects in the managed heap which are no longer in use by the application and it performs the necessary operations to release the memory.

Advantages
  • It allows developing an application without worrying to free memory.
  • It allocates the memory for objects efficiently on the managed heap.
  • It releases the memory of the no longer used objects and reallocates the free memory for future allocations.
  • It provides security of memory by ensuring that an object cannot use the content of another object.

 

Allocation of Memory in Managed Heap

Managed heap is a sequence of allocated memory segments to store and manage the objects. When the new object is created the memory is allocated at the next available location on the managed heap, if there is any free memory available. If the memory is insufficient to create the object, the garbage collector will search for the objects (dead objects) which are not in use to release the memory for the new object.

The object is created using new operator and this operator checks that the bytes required by the new object fits into the space allocated to the object. If the object gets fitted then the nextobjptr points to the object in the heap and the object constructor is called and new operator returns the address of the object. Let us have the diagrammatic representation of the memory allocation in managed heap:

garbage collection process

The memory in heap is divided into some number of generations. There are three generations:

  • Generation 0 for short alive objects.
  • Generation 1 for medium live objects that are moved from Generation 0.
  • Generation 3 have stable objects.

When the object is created then the memory space is allocated which will be higher. That object will be in the Generation 0 and the memory allocation will be continuous without having any space between the generations of garbage collectors.

Generation 0 – As this is the smaller generation and it contains the new objects. Generation 0 are short-lived objects and they are collected frequently. The objects which survive in the Generation 0 then are promoted to Generation 1. For example: temporary object.

Generation 1 – In this the generation contains the objects which have survived for long in generation 0. Those objects which survive in Generation 1 are then promoted to Generation 2. This generation serves as a buffer between the objects which have short lived and long-lived.

Generation 2 – In this the generation contains the longer lived objects which are promoted from generation 1 and are collected infrequently. For example: object at application level which contains the static data and is available till the duration of the process.

What happens during garbage collection?

The garbage collection has following phases:

  • Marking phase – In the marking phase it finds and creates the list of lived objects.
  • Relocating phase – In this phase it updates the references to the objects which will be compacted.
  • Compacting phase – This phase release the memory which is occupied by the dead objects and compacts the surviving objects.

Performance of Garbage Collection

In this we will describe issues related to garbage collection and memory usage. It tells the issues that are related to the managed heap and explains how we can minimize the effect of garbage collection on our applications. Some of the following are:

  • Performance Analysis Tools
  • Troubleshooting Performance Issues
  • Troubleshooting Guidelines
  • Performance Check Procedures

Performance Analysis Tools: In this some of the tools are available for discovering the memory usage and the garbage collection issues. Some of them are:

  • Memory performance counters.
  • Debugging with SOS.
  • Garbage collection Event Tracing for Windows (ETW) Events.
  • Profiling API
  • Application Domain Resource Monitoring

Troubleshooting Performance Issues: In this we will discuss that we have to first determine whether the issue is related to garbage collection and if it is we select from the following list to troubleshoot the problem. Some of them are:

  • Out of memory exception is thrown.
  • Process using too much of memory.
  • Garbage collector does not reclaim objects fastly.
  • Managed heap is too fragmented.
  • Generation 0 is big.
  • CPU usage is too high during garbage collection.

Troubleshooting Guidelines:

  • Workstation or Server garbage collection – The server garbage collection operates on the multiple threads whereas workstation garbage collection requires the multiple instances of the application to run its own garbage collection threads and compete for the CPU time. 
  • Measuring managed heap size – To measure the managed heap size we have to consider the following points:
    • If we measure the garbage collection after the generation 2 the whole managed heap will be free from the dead objects.
    • If we measure garbage collection after the generation 0 the objects in generations 1 and 2 will not be collected.
    • If we measure before a garbage collection, then we can measure allocation as much possible before the garbage collection starts.
    • Measuring in between garbage collection can be problematic, because the garbage collector data structures are not in a stable state for the traversal and may be not able to give the complete results. 
    • When we are using workstation garbage collection with the concurrent garbage collection, then the reclaimed objects are not compacted, so the heap size can be same or larger.
    • When the physical memory load is too high then the concurrent garbage collection on the generation 2 is delayed.

Performance Check Procedures: Some of the following procedures to know the cause of the performance issue are:

  • It determines whether the problem is caused by garbage collection.
  • It determines whether the out of memory exception is managed.
  • It determines that how much virtual memory can be reserved.
  • It determines whether there is enough physical memory.

Let us have an example to know more about garbage collection:

MaxGeneration: In this property the class GC returns the total number of generations.

using System.IO;
using System;
class GCmax
{
    public static void Main(string[] args)
    {
        try
        {
            Console.WriteLine ("GC maximum generations:" + GC.MaxGeneration);
        }
        catch (Exception oEx)
        {
            Console.WriteLine ("Error.." + oEx.Message);
        }
    }
}

Output - GC maximum generations: 1

In the above code the MaxGeneration property will return the highest generation in the garbage collection. It will count the total number of generations in the GC class which starts from 0. But in this code the output is maximum generations is 1.

Let us have another example to know the total memory and generation using the property GetTotalMemory and GetGeneration:

using System;
class BaseGC
{
    public void Display()
    {	
        Console.WriteLine ("The example method");
    }
}
class GCExample
{
    public static void Main (string[] args)
    {
        try
        {
            Console.WriteLine ("The total memory is:" + GC.GetTotalMemory (false));
            BaseGC oBaseGC = new BaseGC ();
            Console.WriteLine ("BaseGC generation is:" + GC.GetGeneration (oBaseGC));
            Console.WriteLine ("The total memory is:" + GC.GetTotalMemory (false));
        }
        catch (Exception oEx)
        {
            Console.WriteLine ("Error.." + oEx.Message);
        }
    }
} 

Output:

The total memory is: 2784
BaseGC generation is: 0
The total memory is: 7952