📜 ⬆️ ⬇️

Optimization of programs under the Garbage Collector

Not so long ago, a great article appeared on Habré Optimizing garbage collection in a high-loaded .NET service . This article is very interesting because the authors, having armed themselves with the theory, have made the previously impossible: they optimized their application using the knowledge of the work of GC. And if earlier we had no idea how this GC works, now it is presented to us on a platter through the efforts of Konrad Kokos in his book Pro .NET Memory Management . What conclusions did I draw for myself? Let's make a list of problem areas and think about how to solve them.


At a recent CLRium # 5: Garbage Collector workshop, we talked about GC all day. However, I decided to publish one report with a text transcript. This is a report about the conclusions regarding application optimization.



Reduce cross-generational connectivity


Problem


To optimize garbage collection speed, the GC collects the younger generation whenever possible. But to do this, he also needs information about links from older generations (in this case, they are an additional root): the card table.


At the same time, one link from the older to the younger generation forces us to cover the area with a card table:



Those. GC, checking the card table, meeting in it a non-zero value, is forced to check a maximum of 320 objects for the presence of outgoing links in our generation.


Therefore, sparse links to the younger generation will make GC more time consuming.


Decision



Do not allow strong connectivity


Problem


As follows from the phase compression algorithms for objects in SOH:



Therefore, the general strong connectivity of objects can lead to subsidence at GC.


Decision



Monitor segment usage


Problem


With intensive work, a situation may arise when the allocation of new objects leads to delays: the allocation of new segments under the heap and their further decommissioning when cleaning garbage


Decision



Do not allocate memory in loaded sections of code.


Problem


Loaded part of the code allocates memory:



Decision



Avoid unnecessary memory allocations in the LOH


Problem


Placing arrays in LOH leads either to its fragmentation or to the weighting of the GC procedure.


Decision



Where justified and possible, use thread stack


Problem


There are a number of ultra short-lived objects or objects living within the framework of a method call (including internal calls). They create traffic objects


Decision



Release objects as early as possible.


Problem


Conceived as short-lived, objects fall into gen1, and sometimes into gen2.
This results in a heavier GC that lasts longer.


Decision



Calling GC.Collect () is not necessary


Problem


It often seems that calling GC.Collect () will fix the situation.


Decision



Avoid Pinning


Problem


Pinning creates a number of problems:



Decision


If there is no other way, use fixed () {}. This method of fixing does not make a real fix: it only happens when the GC has worked inside the curly braces.


Avoid finalizing


Problem


The finalization is not undetermined:



Decision


Carefully call Dispose ()


Avoid lots of threads


Problem


With a large number of threads, the number of allocation context grows, since they are allocated to each thread:



Decision



Avoid traffic to objects of different sizes.


Problem


When traffic objects of different size and lifetime of fragmentation occurs:



Decision


If you intend to traffic objects:



')

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


All Articles