📜 ⬆️ ⬇️

Garbage collector in the .NET environment

Hello, Great and terrible habrazhiteli!
As I recently learned, not many people know how the garbage collector works. Although I understand that 99% of developers do not really need this, but I would like everyone who develops applications on .NET to know how it works. In this article I will try to briefly describe how the garbage collector actually works.

Basic information about the lifetime of the object


As you know, when initializing an object in memory, it allocates the right place for an object. Using the new keyword results in adding a class object to the so-called managed heap , and a reference to the object is returned.
When creating C # applications, you can safely assume that the .NET runtime will take care of the management heap itself without direct intervention from the programmer. In fact, the “ golden rule” of memory management is:
Place the object in the control heap using the new keyword and forget about it.


After creation, the object will be automatically deleted by the garbage collector when it is no longer needed. The question immediately arises of how the garbage collector determines when the object is not needed?

Let's look at a simple example:
public static void MakeACar() { //  myCar      // Car,      //   Car **  . Car myCar = new Car(); ... } 

')
Note that the reference to the Car object (myCar) was created directly inside the MakeACar () method and was not passed outside of the defining scope (neither as a return value, nor as a ref / out parameter). Therefore, after calling the method, the reference to myCar will be unreachable, and the Car object will be a candidate for removal by the garbage collector . However, it should be understood that there is no guarantee that the object will be deleted immediately after the execution of the MakeACar () method. All that can be assumed at the moment is that when the garbage collection is performed in the CLR environment the next time, the myCar object will be set for deletion.

C ++ programmers are well aware that unless they deliberately take care of deleting objects located in a heap, memory leaks will soon appear. In fact, tracking down memory leaks is one of the most tedious and lengthy aspects of programming in unmanaged environments.

Role of application root elements


To figure out how the garbage collector is determined when the object is no longer needed, you need to know what the application application root elements are . Simply put, a root element is a cell in memory that contains a reference to a heaped object. Strictly speaking, the root elements can be called:


During garbage collection processes, the runtime will examine the objects on the heap to determine if they are still reachable (i.e., root) to the application. To do this, the CLR will create object graphs representing all the objects reachable by the application. In addition, it should be borne in mind that the garbage collector will never create a graph for the same object twice, avoiding the need to perform cyclic reference counting, which is typical for programming in the COM environment.

Object Generations

When trying to detect unreachable code, CLR environment objects do not literally check every object in the heap . Obviously, this would take a lot of time, especially in large projects.
To optimize the process, each object in the heap refers to a certain “generation”. The meaning in the use of generations looks quite simple:
The longer the object is in the heap, the higher the likelihood that it will remain there.

For example, a class defined in the main window of a desktop application will remain in memory until the end of the program. On the other hand, an object that has recently fallen into a heap (for example, those that are in the scope of methods) will most likely become unattainable quickly enough. Worryingly of these assumptions, every object in the heap refers to:


Generations 0 and 1 are called ephemeral .

The garbage collector first analyzes all objects that belong to generation 0. If after their removal there is a sufficient amount of memory, the status of all the surviving objects rises to generation 1. If all objects of generation 0 were checked, but additional space is still required, it will be checked generation objects 1. Objects of this generation, which managed to survive, will become objects of generation 2. if the garbage collector still needs memory, then objects of generation 2 will undergo garbage collection. Since There are no objects above the 2nd generation, the status of the objects will not change.
From the above, we can conclude that newer objects will be deleted faster than older ones.

Parallel garbage collection in .NET 1.0 - .NET 3.5

Before the release of .NET 4.0, the cleaning of unused objects was carried out using the technique of parallel garbage collection . In this model, when performing garbage collection of ephemeral objects, the garbage collector temporarily suspended all active threads within the current process, so that the application could not access the managed heap until the garbage collection process was completed.
At the end of the garbage collection cycle, suspended threads were allowed to continue working again. Fortunately, in .NET 3.5 the garbage collector was well optimized and therefore the associated short interruptions in working with the application rarely became noticeable.
Like optimization, parallel garbage collection allowed cleaning of objects that were not found in any ephemeral generation in a separate stream. This reduced (but did not eliminate) the need to suspend active threads by the .NET runtime. Moreover, parallel garbage collection made it possible to place objects on the heap during the assembly of objects of non-ephemeral generations.

Background garbage collection in .NET 4.0

And finally, I would like to tell you about improving the work of the garbage collector in .NET 4.0.

In .NET 4.0, the garbage collector decides in a different way about suspending threads and cleaning objects in a managed heap, using the background garbage collection technique. Despite its name, this does not mean that all garbage collection now occurs in additional background threads. In fact, in the case of background garbage collection for non-ephemeral generation objects, the .NET runtime can now collect garbage from ephemeral generation objects in a separate background thread.
The garbage collection mechanism in .NET 4.0 has been improved so that it takes less time to suspend the flow associated with garbage collection details. Thanks to these changes, the process of cleaning unused objects of generation 0 and 1 has become optimal. It allows you to get a higher level of application performance.

Conclusion

In conclusion, I would like to say that the garbage collector that is used in .NET 4.0 allows you to optimize the performance of programs and has virtually no effect on performance.
In the next article I will explain how you can personally manage the garbage collection process using the System.G namespace.

More detail: here

Source: https://habr.com/ru/post/125968/


All Articles