English Original: Maoni Stephens, compilation: Zhao Yukai (@ Jade Kai Sir)
The CLR garbage collector divides objects by the amount of space they occupy. Large objects and small objects are handled in a very different way. For example, memory defragmentation-the cost of moving large objects in memory is expensive, so let's look at how the garbage collector handles large objects, and how large objects have a potential impact on program performance.
Large object heap and garbage collection
In. Net 1.0 and 2.0, this is considered a large object if the size of an object exceeds 85000byte. This number is based on the experience of performance optimization. When an object requests a memory size that reaches this threshold, it is allocated to the large object heap. What does that mean? To understand this, we need to understand. NET garbage collection mechanism.
As most people know,. Net GC is recycled as "generation". The objects in the program were 3 generations, 0 generations, 1 generations and 2 generations, and 0 generations were the youngest objects, and 2 generations of objects survived the longest. GC Garbage collection is also for performance reasons, and the usual objects will be recycled in 0 generations. For example, in an ASP. NET program, the objects associated with each request should be reclaimed at the end of the request. Objects that are not recycled become 1-generation objects, meaning that the 1-generation object is a buffer between the resident memory object and the immediately extinct object.
From the perspective of generation, large objects belong to the 2 generation object, because large objects are processed only when the 2 generation is recycled. When a generation of garbage collection executes, a younger generation of garbage collection is performed at the same time. For example: When 1 generations of garbage collection will be collected at the same time 1 and 0 generations of objects, when the 2 generation garbage collection will be carried out 1 generation and 0 generations of recycling.
Generation is the logical view of the garbage collector to differentiate memory areas. From a physical storage perspective, objects are allocated on different managed heaps. A managed heap (managed heap) is a memory area that the garbage collector requests from the operating system (by calling Windows API VirtualAlloc). When the CLR loads memory, it initializes two managed heaps, a large object heap (Loh–large object heap), and a small object pair (Soh–small object heap).
A memory allocation request is a managed object that is placed on the corresponding managed heap. If the size of the object is less than 85000byte, it will be placed on the SOH, otherwise it will be placed on the Loh.
For Soh, the object enters the next generation after the garbage collection is performed. That is, if the first garbage collection, the surviving object will enter the second generation, if after the 2nd garbage collection, the object is still not garbage collected, it will become a 2-generation object, 2-generation object is the oldest object is not in the ascending algebra.
When a garbage collection is triggered, the garbage collector will defragment the small object heap and move the surviving objects together. For large object heaps, because of the overhead of moving memory, the CLR team chooses to simply clear them and make a list of the objects that are reclaimed, so that the next time a large object is requested to use the memory, the adjacent garbage objects are merged into a block of free memory.
Keep in mind that the large object heap is not defragmented in. Net 4.0 and may be done in the future. So if you want to allocate large objects and don't want them to be moved, you can use the fixed statement.
As the next small object heap of the Soh recovery
There were four objects obj0-3 before the first garbage collection; Obj1 and obj3 were recycled after the first garbage collection, while Obj2 and Obj0 moved together; There were three objects allocated before the second garbage collection obj4-6 Obj2 and Obj5 were recycled after the second garbage collection, and Obj4 and Obj6 were moved to Obj0.
Is the large object heap Loh Reclaim
You can see that there are four objects obj0-3 before garbage collection is performed; After the first second generation garbage collection, obj1 and obj2 were recycled, and the space occupied by Obj1 and Obj2 was merged after the garbage collection. When the OBJ4 application allocates memory, it allocates the space freed by Obj1 and Obj2 and leaves a fragment of memory. If the size of this fragment is less than 85000byte, then the fragment will never be reused in this program's life cycle.
If there is not enough free memory on the large object heap to accommodate the large object space to be requested, the CLR first attempts to request memory from the operating system, and if the request fails, it triggers a second-generation recycle to try to free some memory.
During the 2 generation garbage collection, unwanted memory can be returned to the operating system via VirtualFree. The process of return see:
When do you recycle large objects?
Before discussing when to recycle a large object, look at what time the normal garbage collection operation is going to take. Garbage collection occurs under the following conditions:
1. The requested space exceeds the 0-generation memory size or the threshold of the large object heap, and most of the managed heap garbage collection occurs in this case
2. When the Gc.collect method is called in the program code, garbage collection of all generation objects, including garbage collection of the large object heap, is performed when the Gc.collect method is called to pass in the gc.maxgeneration parameter
3. When the application receives high memory notifications from the operating system when the operating system is low on memory
4. Second generation garbage collection is triggered if the garbage collection algorithm considers that doing second-generation recycling is effective
5. Each generation of object heaps has a space-size threshold attribute, and when you assign an object to a generation, you increase the total amount of memory close to the threshold of that generation, or the allocation object causes the heap size of this generation to exceed the heap threshold, a garbage collection occurs. Therefore, when you assign small objects or large objects, you will consume a threshold value of 0-generation heap or large object heap. When the garbage collector promotes object algebra to 1 generations or 2 generations, it consumes 1, 2 generation thresholds. These thresholds are dynamically variable during program operation.
Large Object Heap Performance impact
Let's first look at the cost of allocating large objects. The CLR allocates memory for each new object to ensure that the memory is emptied and is not used by other objects (I give out is cleared). This means that the cost of the allocation is fully controlled at the cost of Cleanup (clearing) (unless a garbage collection is triggered at the time of allocation). If emptying the 1byte requires 2 cycles (cycles), it means that it takes 170,000 cycles to clear one of the smallest large objects. Typically, people do not allocate oversized objects, such as allocating 16M-sized objects on a 2GHz machine, which requires about 16ms to empty memory. The price is too high.
Let's look at the cost of recycling. As mentioned earlier, large objects and 2-generation objects are recycled together. A collection of 2-generation objects is triggered if a large object or 2-generation object occupies more space than its threshold. If the 2-generation collection is triggered because the large object heap exceeds the threshold, there are not many objects in the 2-generation object heap that can be recycled. If there are not many objects on the 2-generation heap, this is a small problem. But if the 2-generation heap is large, too many 2-generation recoveries can cause performance problems. If you are allocating large objects on a temporary basis, you will need a lot of time to run garbage collection, which means that if you continue to use large objects and then release large objects, you will have a significant negative impact on performance.
Huge objects on the large object heap are usually arrays (very few objects are very large). If the elements in the object are strongly referenced, the cost is high, and if there is no mutual reference between the elements, garbage collection does not need to traverse the entire array. For example, using an array to hold the nodes of a binary tree, one way is to strongly reference the left and right nodes in the node:
Class Node{data D; Node left; Node right;} node[] BinaryTree = new Node[num_nodes];
If Num_nodes is a large number, it means that each node needs to see at least two reference elements. An alternative is to keep the array index number of the left and right node elements in the node
Class Node{data D;uint left_index;uint right_index;}
In this case, the reference relationship between the elements is removed, and the referenced node can be obtained by binarytree[left_index]. The garbage collector does not need to look at the relevant reference elements when it does garbage collection.
Collecting performance data for a large object heap
There are several ways to collect performance data related to large object heaps. Before I explain these methods, let's talk about why we need to collect the performance data related to the large object heap.
When you start collecting performance data for a particular aspect, it's possible that you've found evidence that this is causing a performance bottleneck, or that you haven't looked through all the areas and found no problems.
When looking for performance issues, the. Net CLR Memory Performance counters are usually the tools that should be considered first. The counters associated with the Loh have Generation 2 collectioins (2 Generation heap collection) and the large object heap size for large objects. Generation 2 Collections shows the number of times a 2-generation garbage collection operation occurred after the process started. The Large object Heap size counter displays the size value of the current large object heap, including free space, which is updated after each garbage collection operation, not every allocation of memory.
You can refer to observing. Net CLR Memory related performance data in Windows performance counters
You can also query the values of these counters through a program, and many people collect performance counters to help find performance bottlenecks.
Of course, you can also use the debugger winddbg to observe the large object heap.
The final hint: so far, the large object heap as part of garbage collection is not to do memory defragmentation, but this is only a CLR implementation details, program code should not rely on this feature. If you want to make sure that the object is not moved by the garbage collector, use the fixed statement.
Original address: http://www.php.cn/
The above is the content of. Net garbage collection and large object processing, please pay attention to topic.alibabacloud.com (www.php.cn) for more related content!