SoFunction
Updated on 2025-03-01

.Net's GC garbage collection principle and implementation

1. First understand the necessary knowledge prerequisites

Hosted and unmanaged in memory can be simply understood as:

Hosting: Data objects that can be released from memory with the help of GC (the content points to be described below)

Unmanaged: Objects that must be manually released with the help of Dispose (implemented from IDisposable)

There is a conceptual distinction between stack and heap in memory, and only a brief explanation:

Stack: Features of first in and later out (I will not elaborate on it in detail here)

Heap: Memory space for storing data object instances (the content point to be described below)

2. A simple description of .Net GC

GC garbage collection is a process of processing the memory heap.

When an application process is created, a virtual continuity memory space is allocated to the physical memory heap to provide the generated data object instances stored during subsequent runs of the application.

GC is an independent process used to automatically maintain and manage space allocation and release in the memory heap. It carries out garbage collection through one or more threads, and backend thread garbage collection is enabled by default. (Foreground threads and background threads, please refer to other ones)

3. When will GC garbage collection on the .Net platform be triggered?

1. When there is insufficient virtual memory space in the allocated heap, the system will automatically recycle/compress/enlarge the allocated virtual memory blocks to adapt to the newly generated data object storage.

2. When the entire physical memory is not enough, the system will automatically recycle/compress the memory space occupied by each process to adapt to the newly generated data object storage.

3. When GC recycling is manually triggered in the application, GC collects garbage in the manually specified method.

4. Understand the generation in the heap from the scope

Let's understand this first

Assuming that an instance variable has a larger scope when declared, it will not be recycled immediately, because the factors with large scope may be used in subsequent programs.

Assuming that an instance variable has a smaller scope when declared, it may be recycled first, because the survival period is short and after the scope scope, this variable will no longer be used.

Assuming a static or global scope variable, it is usually not recycled because such a global declaration will be used for a long time in any code segment.

Therefore, in order to better recycle, the data object instances are summarized in the heap into: 0 generation, 1 generation, 2 generation

Generation 0: Temporary or latest created data object instance. The most commonly recycled object instance.

Generation 1: Data object instance used again for a period of time, data object instance with a longer life cycle. Object instances that are rarely recycled.

Generation 2: Object instances of permanent memory, such as: static type, global scope, etc. Usually recycled after the application exits.

5. Transfer of objects in the heap between generations: the promotion of survivors

The application is running continuously.

The newly created object is first placed in generation 0. After running for a period of time, some variables exceed their scope and will no longer be used, and will be cleaned up by GC;

Since some variables have large scopes and have not yet exceeded their scope, they may be used in the future, so the GC will not be cleaned;

In Generation 0, some data object instances will be cleaned by GC, and some data instance objects will not be cleaned by GC. So, we call the data object instances that have not been cleaned by GC.

At this time, the survivors in the 0th generation will be transferred to the 1st generation (think about which type of object instance is stored by the 1st generation above...);

Then, and so on, the object instances that have been used for a long time/everything will be transferred from generation 1 to generation 2;

Therefore, the object instances stored in the second generation are usually static or global scoped or long-term used.

6. How does GC determine the instance of the object to be cleaned?

GC generates a structure diagram between each object in the heap, as the basis for recycling objects, and finds inactive objects.

The associated reference relationship between all data object instances will generate a complete structure diagram. Some object instances that are not in the structure diagram or that are beyond the scope or are no longer used are called inactive objects. It is considered as the object to be cleaned by the GC.

To be precise:

  • Stack root
  • Garbage recycling handle
  • Static data

7. Manual GC garbage collection

In some uncommon situations, forced recycling can improve the performance of your application. Here, garbage collection can be enforced using methods to induce garbage collection.

Note that it is induction, not immediate recycling.

In order to take into account the current stable operation of the application, execution does not necessarily have an immediate effect. This is just a trigger, and the objects to be recycled will be collected, and the recycling action will be performed at a certain appropriate time period in the future. (Of course, you can also force blocking recycling, skip it here)

(Think about: useless instance = null, does it tell GC to be a recyclable object? The effect after () again.)

Regarding the parameters of the method, the above-mentioned concepts and scenarios will be used:

  • Recycle the specified agent
  • Specify the number of recycling times
  • Forced recycling or at the right time
  • Blocking Recycling or Background Thread Recycling
  • Compress or clean

(Blocking recycling method: stop for a while, let me recycle it first)

Of course, it is usually recommended: 0 generation, choose the opportunity, and background recycling (blocking risk is too high, usually choose the opportunity method, and consider it specifically)

8. Weak references in the memory heap

When the application is executing an object in use, it is impossible for GC to recycle it, so the application is considered to have a strong reference to the object.

Strong reference: The object instance that the application is using cannot be recycled by GC.

Weak reference: An object instance that the application has not used temporarily can be temporarily defined by GC as a recyclable instance. Before recycling, it can also become a strong reference after being used again by the application.

Suppose that an object instance is cleaned up by GC and then used again in the subsequent scenario, the object instance will be recreated. If this object instance is relatively large, it will be frequently created...

Of course there is still room for optimization, so weak reference optimizes the above scenarios.

Advantages of weak references: For frequently created large instances, weak types can be created and used multiple times at a time, avoiding the performance consumption of multiple creation of large object instances.

(Is the performance consumption in object management caused by using weak types for small objects worth it)

To create a weak reference to an object, create a WeakReference using the instance of the object you want to track. Then set the Target property to the object and the original reference to the object is null. (Refer to the official document)

In other words: we can customize which object instances should not be garbage collected by GC for the time being.

9. Garbage collection when multiple applications share memory

When multiple applications are running on a host at the same time, the allocation of memory space size is recommended to be flexible and variable to achieve the balance and stability of memory utilization by each application.

If the gcTrimCommitOnLowMemory setting is enabled, the garbage collector calculates the system memory load and enters trimming mode when the load reaches 90%. Unless the load drops to less than 85%, it will remain in trimming mode.

If the conditions allow, the garbage collector can decide that the gcTrimCommitOnLowMemory setting is not helpful to the current application and ignores it.

Enable gcTrimCommitOnLowMemory settings as follows

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <runtime>
        <gcTrimCommitOnLowMemory enabled="true"/>
    </runtime>
</configuration>

This is the article about the principles and implementation of .Net GC garbage collection. For more related .Net GC garbage collection, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!