I. Generation)
The age division refers to the division of objects in heap according to the length of time. The shortest score is in The 0th generation, and the longest score is in the 2nd generation. The objects in the 2nd generation are usually relatively large. The generation level is related to the Framework version, which can be known by calling GC. maxgeneration.
In general, GC collects the most recently allocated objects (0th generations) first, which is exactly the same as the "least recently used" Algorithm of the classic memory paging algorithm in the operating system. However, this does not mean that GC only collects recently allocated objects ,. net GC divides the heap space into three generations based on the lifetime of the object: The newly allocated object is in The 0th generation (the maximum length of the 0 generation space is usually 256 K), and is allocated in the address order, they are usually some local variables; the 1st generation (the maximum space length of the 1 generation is usually 2 MB) is an object that remains in the memory after the 0 generation of garbage collection, they are usually some objects, such as forms and buttons. The 2nd generation is the objects that still reside in the memory after several garbage collection, and they are usually some application objects.
When the memory is tight (for example, the 0-generation object is full), GC is transferred to the execution engine-that is, CLR-to mark, compress, and recycle the 0th-generation space, this is usually less than 1 ms. If the memory is still tight after recovery, GC will continue to recycle 1st generations (usually less than 10 milliseconds) and 2nd generations, of course, GC sometimes does not collect garbage in the order of 0th, 1, and 2, depending on the running situation, or manually call GC. collect (I) specifies the collection generation. When the 2nd generation is recycled, the system will throw an outofmemoryexception if the system cannot obtain enough memory.
After several GC operations, if an object in generation 0 still exists, it will be moved to generation 1st. Similarly, the 1st and 2 generations run in the same logic.
The number and capacity of generation in GC heap are variable (this is controlled by a "policy engine" and will be introduced to "policy engine" in section 2 "), the following code uses windbg to illustrate this problem. In the following code, you can click the button "button1" to continuously allocate memory and obtain the age of the object ", in addition, the age of "a" is also obtained when the form is loaded.
See the source code example:
Public partial class form1: Form
{
Private string a = new string ('A', 1 );
Public form1 ()
{
Initializecomponent ();
}
Private void button#click (Object sender, eventargs E)
{
A = new string ('A', 900000 );
Label1.text = GC. getgeneration (a). tostring ();
}
Private void form1_load (Object sender, eventargs E)
{
Label1.text = GC. getgeneration (a). tostring ();
}
}
When the program is loaded, the generation of "a" is 0th. We can obtain the following information through windbg:
Http://www.lmwlove.com/ac/ID789 (picture)
It can be seen that the GC heap is divided into two segments, three generations, with the decimal difference of the starting address of each generation being 12.
After clicking the "button1" button several times, the generation age of "a" is increased to 2nd, and the following information is obtained through windbg:
Http://www.lmwlove.com/ac/ID789 (picture)
Note that the difference between the start (Generation X starts at) decimal address of each generation is no longer 12. The difference between generation 0 and generation 1 is 98904, and that between generation 1 and generation 2 is 107908, this indicates that the generation size is changing as the program runs, and the GC heap size also changes.
Ii. Algorithms
The essence of the garbage collector is to track all referenced objects, sort out objects that are no longer referenced, and recycle the corresponding memory.
This sounds like a reference counting algorithm. However, this algorithm needs to traverse all objects and maintain their references, so it is less efficient, in addition, memory leakage is easily caused when "Ring reference" occurs. Therefore,. net uses a mark sweep algorithm to complete the preceding tasks.
"Clear" -- reclaim memory: Enable the Compact algorithm to move the surviving objects in the memory, modify their pointers, and keep them in the memory. In this way, the idle memory will continue, this solves the memory fragmentation problem. When the new object is allocated with memory again, the CLR does not have to find the memory space suitable for the new object in the memory filled with fragments, so the allocation speed will be greatly improved. Except for large objects (large object heap), GC won't move a big bully in memory because it knows that the current CPU is not cheap. Generally, large objects have a long lifetime when a large object is in. when a net managed heap is generated, it is allocated in a special part of the heap. the overhead of moving large objects exceeds the performance that can be improved by sorting out this heap.
In addition to increasing the memory allocation rate, the Compact algorithm improves the cache performance if the newly allocated objects are in a tight position in the heap, because objects allocated together are often used together (Program Locality Principle), it is very important to provide a continuous blank memory space for the program.
"Mark" -- spam recognition:
Starting from the root of the application, the system uses the mutual reference relationship to traverse all the objects dynamically allocated on the heap. The objects not referenced are not marked and become garbage; the surviving object is marked as a root-object reachable graph ".
Actually, CLR regards object relationships as "tree graphs". Undoubtedly, anyone who understands the data structure knows that the concept of "tree graphs" will speed up object traversal.
Detecting and marking object references is an interesting thing. There are many ways to do this, but only one is the most efficient ,. net is completed by using stacks, and the detection is completed in the continuous inbound and outbound stacks: first, select an object to be detected in the tree graph, press all references of the object to the stack until the stack becomes empty. Empty stack means that all objects that can be reached by the local root (or node in the tree chart) have been traversed. The node range of the tree chart includes local variables (in fact, local variables will be recycled soon, because of its obvious scope and good control), registers, static variables, and these elements need to repeat this operation. Once completed, the memory is checked by objects one by one, and unmarked objects become garbage.
This article comes from: http://www.lmwlove.com/ac/ID789