Principle and implementation of GC garbage collection based on. Net

  • 2021-11-29 23:35:14
  • OfStack

1. Understand the necessary knowledge premise first

Managed and unmanaged in memory can be simply understood as:

Managed: Data objects that can be released from memory with GC (content points to be described below)

Unmanaged: Objects that must manually release resources with Dispose (implemented from IDisposable)

There is a conceptual distinction between stack and heap in memory, which is only briefly explained:

Stack: Features of first in, last out (not elaborated here)

Heap: Memory space for storing instances of data objects (content points to be described below)

2.. A brief description of Net GC

GC garbage collection is the processing of the memory heap.

When an application process is created, a block of virtual continuous memory space is allocated in the physical memory heap for this application to store the generated data object instances when the application is subsequently run.

GC is a stand-alone process that automatically maintains and manages the allocation and release of space in the memory heap. It collects garbage through one or more threads, and background thread garbage collection is enabled by default. (For foreground threads and background threads, please refer to others.)

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

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

2. When the whole 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 collection is manually triggered in the application, GC collects garbage in the manually specified way.

4. Understanding Generations in the Heap from a Scope Perspective

Let's understand it like this first

Assuming that an instance variable is declared in a large scope, it will not be recycled immediately, because of the large scope, it is possible that subsequent programs will often be used.

Assuming that an instance variable is declared in a small scope, it is likely to be reclaimed preferentially because of its short life cycle and beyond the scope, the variable will no longer be used.

Assuming a static or global scope variable, it will not normally be reclaimed because such a global declaration will be used in arbitrary code segments for a long time.

Therefore, for better recycling, each data object instance is summarized into generation 0, generation 1 and generation 2 in the heap

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

Generation 1: Data object instances that are reused in a period of time, and data object instances with a long life cycle. Less reclaimed object instances.

Generation 2: Object instances that live in memory, such as statically typed, globally scoped, etc. Usually recycled after the application exits.

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

The application is running continuously,

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

Because some variables have large scope, they have not exceeded their own scope at present, and may be used later, so GC will not clean up;

In generation 0, some data object instances will be cleaned by GC, and some data instance objects will not be cleaned by GC. Then, the data object instances that have not been cleaned by GC are called survivors.

At this point, survivors from Generation 0 will be transferred to Generation 1 (think what kind of object instances are stored in Generation 1 mentioned above...);

Then, by analogy, long-term/ubiquitous object instances will be transferred from generation 1 to generation 2;

Therefore, the objects stored in Generation 2 are usually static or globally scoped or long-used object instances.

6. How does GC determine which object instances to clean up?

GC generates the structure diagram between objects in the heap, which is used as the basis for recycling objects and finds out inactive objects.

A complete structure diagram will be generated by the association reference relationship between all data object instances, and some object instances that are not in the structure diagram or out of scope or are no longer used are called inactive objects. Is regarded as the object to be cleaned by GC.

To be precise:

Stack root Garbage collection handle Static data

7. Manual GC garbage collection

In some uncommon cases, forced recycling can improve the performance of applications. Here, you can induce garbage collection by enforcing it using the GC. Collect method.

Note that it is induction, not immediate recovery.

In order to consider the current stable operation of the application, the execution of GC. Collect does not have an immediate effect, here is only a trigger, which will collect the objects to be recycled, and the recycling action will be carried out at a suitable time in the future. (Of course, you can also force blocking recycle, which is skipped here.)

(Think 1: Useless instance = null, whether to tell GC as a recyclable object? The effect after GC. Collect ().)

With regard to the parameters of the GC. Collect method, the concepts and scenarios mentioned above will be used:

Collects the specified generation Specify the number of recycles Forced recycling or opportune recycling Blocking Recycling or Background Thread Recycling Compress or clean

(Blocking recycling method: Stop 1 first, let me finish recycling first)

Of course, it is usually recommended: generation 0, opportunity selection, background recycling (blocking risk is too great, usually choose the opportunity selection method, specific self-consideration)

8. Weak references in the memory heap

When the application is executing an object in use and GC cannot be recycled, the application is considered to have a strong reference to the object.

Strong reference: The object instance being used by the application and cannot be recycled by GC.

Weak reference: An object instance that is temporarily unused by the application, which can be temporarily defined as a recyclable instance by GC, and can become a strong reference before recycling or after being reused by the application.

Assuming that an object instance is cleaned by GC and then used again, the object instance will be recreated. If the object instance is relatively large, such frequent creation......

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

Advantages of weak reference: For frequently created large instances, weak types can be created once and used multiple times, avoiding the performance consumption of creating large object instances multiple times.

(Is it worthwhile to use weak typing for small objects to consume performance on object management?)

To establish a weak reference to an object, create an WeakReference using the object instance you want to trace. Then set the Target property to the object and the original reference to the object to null. (Refer to official documents)

That is, we can customize which object instances are not temporarily garbage collected by GC.

9. Garbage Collection in Multiple Applications of Shared Memory

When multiple applications are running on one host at the same time, it is suggested that the allocation of memory space should be flexible to achieve the balance and stability of memory utilization of 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 be in trim mode.

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

Enable gcTrimCommitOnLowMemory settings as follows


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

Related articles: