Introduction to Garbage Collection in C#

Introduction to Garbage Collection in C#

21 Oct 2024
Beginner
233 Views
10 min read
Learn with an interactive course and practical hands-on labs

Free C# Foundation Course: Learn C# In 21 Days

Garbage Collection in C#

Garbage Collection in C# refers to the process by which the Common Language Runtime (CLR) automatically reclaims memory that is no longer in use by an application. You know how when you finish a task, it feels fantastic to clear your desk and make way for new items? That's basically what Garbage collection does in C#. It automatically cleans up memory that your software no longer requires. It not only keeps your software running smoothly but also minimizes memory leaks.

So, In this C# Tutorial, we will explorewhat garbage collection is in C#includingHow Garbage Collection Works in C#.

How Garbage Collection Works in C#

The Garbage Collector in C# takes a generation-based approach, dividing things into distinct generations based on their lifespan.

  • Generation 0:This generation stores short-lived objects that are often collected fast.
  • Generation 1:Generation 1 holds objects that have survived at least one garbage collection.
  • Generation 2: ItContains long-lived objects that persist for a longer duration.

The GC identifies objects that are no longer reachable, marks them for collection, and frees up the memory they occupy.

Heap Generations in Garbage Collection

The Garbage Collector (GC) in C# uses a generational collection strategy to optimize memory management. The heap is divided into three generations:

1. Generation 0 (Gen 0)

This is where newly created, short-lived objects are stored. These objects are collected frequently because most of them quickly become unreachable. Example: temporary objects like local variables in methods.

2. Generation 1 (Gen 1)

Generation 1 holds objects that survived one garbage collection in Generation 0. It acts as a buffer between short-lived and long-lived objects.

3. Generation 2 (Gen 2)

This generation contains long-lived objects, such as global variables or objects that stay in memory for extended periods. It is collected less often to avoid performance overhead.

Key Methods in the GarbageCollector Class

  • GC.Collect(): Forces garbage collection to occur. You can specify a generation to collect.
  •  GC.Collect(); // Full GC
     GC.Collect(0); // Collect Generation 0
  • GC.GetTotalMemory(): Returns the total memory currently allocated.
  •  long memoryUsed = GC.GetTotalMemory(false);
  • GC.MaxGeneration: Returns the maximum number of generations (usually 2).
  •  int maxGen = GC.MaxGeneration;
  • GC.GetGeneration(): Returns the generation of a specific object.
  •  int gen = GC.GetGeneration(myObject);
  • GC.SuppressFinalize(): Prevents the finalizer from being called on an object.
  •  GC.SuppressFinalize(myObject);
  • GC.WaitForPendingFinalizers(): Suspends the thread until finalizers are completed.
  •  GC.WaitForPendingFinalizers();

Sample Program

Here’s a simple program that demonstrates garbage collection and generation handling:

 using System;

class Program
{
    static void Main(string[] args)
    {
        // Display total memory used before object creation
        Console.WriteLine("Memory before creating objects: {0} bytes", GC.GetTotalMemory(false));

        // Create a large number of objects in Generation 0
        for (int i = 0; i < 10000; i++)
        {
            object obj = new object();
        }

        // Display memory used after creating objects
        Console.WriteLine("Memory after creating objects: {0} bytes", GC.GetTotalMemory(false));

        // Force garbage collection of Generation 0
        GC.Collect(0);
        Console.WriteLine("Memory after GC.Collect(0): {0} bytes", GC.GetTotalMemory(false));

        // Create an object and check its generation
        object genObject = new object();
        Console.WriteLine("Generation of genObject: {0}", GC.GetGeneration(genObject));

        // Force full garbage collection (all generations)
        GC.Collect();
        Console.WriteLine("Memory after full GC.Collect(): {0} bytes", GC.GetTotalMemory(false));

        // Suppress finalization for an object
        GC.SuppressFinalize(genObject);
        Console.WriteLine("Generation of genObject after suppression: {0}", GC.GetGeneration(genObject));

        // Display the maximum number of generations
        Console.WriteLine("Max Generation: {0}", GC.MaxGeneration);
    }
}     

Output Example

 Memory before creating objects: 13000 bytes
Memory after creating objects: 23000 bytes
Memory after GC.Collect(0): 14000 bytes
Generation of genObject: 0
Memory after full GC.Collect(): 13000 bytes
Generation of genObject after suppression: 0
Max Generation: 2
        

Phases of Garbage Collection

Garbage Collection typically follows these three phases:

Phases of Garbage Collection

  • Marking: Identifies which objects are still reachable and marks them as alive.
  • Relocating: Moves live objects to fill the gaps left by dead objects.
  • Compacting: Compacts memory to reduce fragmentation, ensuring efficient future allocations.

Generational Collection in Action

The GC typically starts with Generation 0. If there’s still not enough memory after collecting Generation 0, it proceeds to Generation 1, and finally Generation 2 if necessary.

When Does Garbage Collection Occur?

Garbage Collection in C# occurs in the following scenarios:

  • Memory Allocation: When memory is low, the GC is triggered to free up space.
  • Manual Invocation:You can manually trigger GC using GC.Collect(), though it is generally discouraged.
  • Application Idle Time: The GC may run during idle periods to optimize memory usage.

key features of the garbage collector in C#

1. Automatic Memory Management

The Garbage Collector (GC) automatically manages memory allocation and deallocation, eliminating the need for developers to manually free memory. This reduces the likelihood of memory-related bugs like leaks and crashes.

2. Generational Collection

The GC organizes objects into three generations, focusing on short-lived objects first for more efficient memory management:

  • Generation 0: Holds short-lived objects and is collected frequently.
  • Generation 1: Stores objects that have survived Generation 0 collection.
  • Generation 2: Contains long-lived objects, collected less often.

3. Compaction and Memory Optimization

After collecting objects, the GC compacts memory to eliminate gaps left by dead objects, reducing fragmentation and making memory allocations faster.

4. Mark-and-Sweep Algorithm

The GC uses a mark-and-sweep algorithm, where it marks live objects and sweeps away objects that are no longer reachable, reclaiming their memory.

5. Background and Concurrent Garbage Collection

The GC can run in the background or concurrently with your program’s execution, reducing interruptions and improving overall application performance.

6. Large Object Heap (LOH) Management

The GC manages large objects separately in a special Large Object Heap (LOH). This reduces the performance impact when handling large memory allocations.

7. Finalization Support

C# provides support for finalization, allowing objects to release unmanaged resources (such as file handles or network connections) before being collected by the GC.

8. Manual Garbage Collection

Although the GC is automatic, developers can manually invoke it using the GC.Collect() method. However, this should be done cautiously, as frequent manual collection may negatively affect performance.

9. Low-Latency Modes

The GC provides low-latency modes for high-performance or real-time applications where minimizing GC interruptions is critical.

10. Efficient Memory Allocation

The GC optimizes memory allocation for new objects, making the allocation process fast and minimizing overhead in most scenarios.

Advantages of Garbage Collection

Key benefits of garbage collection include:

  • Automatic Memory Management: Developers are freed from manual memory allocation and deallocation.
  • Memory Leak Prevention: GC automatically reclaims memory from unused objects, preventing memory leaks.
  • Efficient Generational Collection: By focusing on short-lived objects, the GC works efficiently.
  • Application Stability: Proper memory management reduces crashes and slowdowns due to excessive memory consumption.

Best Practices for Optimizing Garbage Collection

Though automated, you can optimize memory management with the following practices:

  • Minimize Large Object Allocations: Large objects are more expensive to collect and store in a special Large Object Heap (LOH).
  • Reduce Object Creation: Avoid creating unnecessary objects, especially in loops or frequently called methods.
  • Explicitly Dispose of Objects: Use the IDisposable interface and the Dispose() method to release unmanaged resources.
  • Use GC.Collect() Sparingly: Manually triggering garbage collection can harm performance and should be done carefully.

Read More: If you are preparing for the C# exam or interview "Top 50 C# Interview Questions and Answers "Might help you.

    Conclusion

    Garbage Collection in C# simplifies memory management, helping developers avoid common issues such as memory leaks and fragmentation. With its generational approach, C# GC optimizes performance by focusing on short-lived objects. By following best practices, you can further optimize the efficiency of garbage collection in your applications. Consider our .NET Certification training because it provides a comprehensive understanding of C# programming language.

    FAQs

    Garbage collection (GC) is a memory recovery feature built into programming languages such as C# and Java. 

    In C#, the garbage collector is responsible for managing memory and automatically freeing up memory that is no longer being used by the application.

    You avoid GC by avoiding allocations. Pre-allocate everything you can into object pools, and use the pools along with struct and stack alloc to avoid heap allocations during your main program loop

    Take our Csharp skill challenge to evaluate yourself!

    In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.

    GET FREE CHALLENGE

    Share Article
    About Author
    Shailendra Chauhan (Microsoft MVP, Founder & CEO at Scholarhat by DotNetTricks)

    Shailendra Chauhan, Founder and CEO of ScholarHat by DotNetTricks, is a renowned expert in System Design, Software Architecture, Azure Cloud, .NET, Angular, React, Node.js, Microservices, DevOps, and Cross-Platform Mobile App Development. His skill set extends into emerging fields like Data Science, Python, Azure AI/ML, and Generative AI, making him a well-rounded expert who bridges traditional development frameworks with cutting-edge advancements. Recognized as a Microsoft Most Valuable Professional (MVP) for an impressive 9 consecutive years (2016–2024), he has consistently demonstrated excellence in delivering impactful solutions and inspiring learners.

    Shailendra’s unique, hands-on training programs and bestselling books have empowered thousands of professionals to excel in their careers and crack tough interviews. A visionary leader, he continues to revolutionize technology education with his innovative approach.
    Accept cookies & close this