In-depth. NET Managed Heap)

Source: Internet
Author: User
Among all. NET technologies, the most controversial one is probably Garbage Collection (GC. As an important part of the. NET Framework, hosting heap and garbage collection mechanisms are unfamiliar to most of us. In this article, we will discuss the benefits of hosting the heap and you.
Why is heap managed?
The. NET Framework contains a managed heap. All. NET languages use it when allocating reference type objects. Lightweight objects such as value types are always allocated to the stack, but all class instances and arrays are generated in a memory pool. This memory pool is a managed heap.
The basic algorithm of the garbage collector is simple:
● Mark all managed memory as spam
● Search for memory blocks being used and mark them as valid
● Release all unused memory blocks
● Organize the heap to reduce fragments
Managed heap Optimization
It seems very simple, but the steps actually taken by the garbage collector and other parts of the heap management system are not trivial, and they often involve the optimization design to improve performance. For example, garbage collection traversing the entire memory pool has a high overhead. However, research shows that most objects allocated on managed stacks only have a short lifetime, so the heap is divided into three segments, called generations. The newly allocated object is placed in generation 0. This generation is the first to be recycled-in this generation, it is most likely to find memory that is no longer in use, because it is small (small enough to be put into the L2 cache of the processor ), therefore, the recovery in it will be the fastest and most efficient.
Another optimization operation for hosting heap is related to the locality of reference rule. This rule indicates that objects allocated together are often used together. If the objects are in a tight position in the heap, the high-speed cache performance will be improved. Because of the nature of hosting heap, objects are always allocated on consecutive addresses, and managed heap is always compact. As a result, objects are always close to each other and never get far apart. This is in stark contrast to the unmanaged code provided by the standard heap. In the standard heap, the heap can easily become fragments, and the objects allocated together are often far away from each other.
Another optimization is related to large objects. Generally, large objects have a long lifetime. When a large object is generated in the. NET managed heap, it is allocated in a special part of the heap, which will never be organized. Because the overhead of moving large objects exceeds the performance that can be improved by sorting out these sub-stacks.
External Resources
The garbage collector can effectively manage resources released from the managed heap, but the resource recycling operation is only executed when the memory is insufficient and a collection action is triggered. So how does a class manage limited resources such as database connections or window handles? Wait until the garbage collection is triggered and then clean up the database connection or file handle is not a good method, which seriously reduces the system performance.
All classes with external resources should execute the Close or Dispose method when these resources are no longer used. Starting from Beta2 (all Beta2 in this Article refers to. NET Framework Beta2, which is not explicitly stated), The Dispose mode is implemented through the IDisposable interface. This will be discussed later in this article.
The class that needs to clear external resources should also implement a finalizer operation ). In C #, the preferred method to create a termination operation is to implement it in the destructor, while in the Framework layer, the termination operation is implemented by reloading the System. Object. Finalize method. The following two methods to terminate an operation are equivalent:
~ OverdueBookLocator ()
{
Dispose (false );
}
And:
Public void Finalize ()
{
Base. Finalize ();
Dispose (false );
}
In C #, terminating the operation in both the Finalize method and the Destructor will result in errors.
Unless you have enough reason, you should not create the Destructor or Finalize method. Terminating the operation will reduce the system performance and increase the memory overhead during the execution period. At the same time, due to the method in which the operation is terminated, you cannot guarantee when the operation will be terminated.
Details of memory allocation and garbage collection
After having a general impression on GC, let's discuss details about the allocation and recycling work in the managed heap. Hosting heap looks like a traditional heap in C ++ programming that we are already familiar. In the traditional heap, the data structure is used to using large idle memory. Finding memory blocks of a specific size is a very time-consuming task, especially when the memory is full of fragments. In the managed heap, memory is grouped into consecutive arrays, and pointers always move between the used memory and the unused memory. When the memory is allocated, the pointer simply increments. One advantage of this is that the efficiency of the allocation operation has been greatly improved.
When objects are allocated, they are initially placed in generation 0. When the size of generation 0 is about to reach its upper limit, a recycling operation executed only in generation 0 is triggered. Because the size of generation 0 is small, this is a very fast GC process. The result of this GC process is to completely refresh generation 0. Objects that are no longer in use are released. objects that are actually in use are organized and moved to generation 1.
When the size of generation 1 is close to its upper limit as the number of objects migrated from generation 0 increases, A collection action is triggered to execute the GC process in generation 0 and generation 1. As in generation 0, objects that are no longer in use are released, used objects are organized and moved into the next generation. The main goal of most GC processes is generation 0, because in generation 0, there may be a large number of temporary objects that are no longer in use. This process has a high overhead for the collection process of generation 2, and will be triggered only when the GC process of generation 0 and generation 1 cannot release enough memory. If the GC process of generation 2 still cannot release enough memory, the system will throw an OutOfMemoryException
The garbage collection process for objects with termination operations is slightly more complex. When an object with a termination operation is marked as spam, it is not immediately released. Instead, it will be placed in a finalization queue, which creates a reference for this object to prevent this object from being recycled. The background thread executes their respective termination operations for each object in the queue, and deletes the object that has already executed the termination operation from the termination queue. Only objects that have been terminated will be deleted from the memory during the next garbage collection process. One consequence of this is that the object waiting for termination may be moved into a higher-level generation before it is cleared, thus increasing the delay time for it to be cleared.
The object that needs to terminate the operation should implement the IDisposable interface so that the client program can quickly perform the termination action through this interface. The IDisposable Interface contains a method called Dispose. This interface introduced by Beta2 is implemented in a mode that has been widely used before Beta2. Essentially, an object that needs to terminate an operation exposes the Dispose method. This method is used to release external resources and suppress termination operations, as shown in the following program snippet:
Public class OverdueBookLocator: IDisposable
{
~ OverdueBookLocator ()
{
InternalDispose (false );
}
Public void Dispose ()
{
InternalDispose (true );
}
Protected void InternalDispose (bool disposing)
{
If (disposing)
{
GC. SuppressFinalize (this );
// Dispose of managed objects if disposing.
}
// Free external resources here
}
}

Objects can be cleared in two ways. The first method isIDisposableInterfaceDisposeMethod. This method is called by the client code when the object ends explicitly.InternalDispose (true). In this case, all objects are cleared. If the Destructor is calledInternalDispose (false)Called. Only external resources are released. If we have already terminated the operation, our own objects may have been released, and subsequent references to them may cause exceptions.
PairGC. SuppressFinalizeWill prevent the spam collector from placing the object in the termination queue. This can reduce the memory consumption caused by sorting objects during a GC process and improve the performance because the termination operation is not called.
For C #Optimization
ThereforeIDisposable. Dispose ()To release resources is a good way, it not only reduces some memory requirements for operations on the hosting stack, but also reduces the number of objects that must be terminated. However, it is troublesome to use, especially when multiple temporary objects are created. To benefit from the IDisposable interface, the C # client program should write code like the following:
OverdueBookLocator bookLocator = null;
Try
{
BookLocator = new OverdueBookLocator ();
// Use bookLocator here
Book book = bookLocator. Find ("Eiffel, the Language ");
.
.
.
}
Finally
{
If (bookLocator! = Null)
{
IDisposable disp = bookLocator as IDisposable;
Disp. Dispose ();
}
}
FinallyThe code in is used for proper cleaning when an exception occurs. To enable the C # client program to use the Dispose mode in a simple and effective manner, Beta2 introducesUsingExpression.UsingThe expression allows you to simplify your code, so the above Code can be written:

Using (bookLocator = new OverdueBookLocator ())

{

// Use bookLocator here

Book book = bookLocator. Find ("Eiffel, the Language ");

}
You should useUsingExpression. It ensures thatIDisposableAn appropriate call to an interface, even when an exception occurs.
UseSystem. GCClass
System. GCClass is used to access the garbage collection mechanism exposed by. NET framework. This class contains the following useful methods:

  1. GC. SuppressFinalizeThis method has been described earlier and can suppress the termination operation. If you have released the external resources of an object, call this method to suppress the execution of the termination operation on this object.
  2. GC. CollectIt has two versions. Versions without parameters are recycled on all the generations of the managed heap. The other version has an integer parameter that specifies the generation of the recycle operation. You will rarely call this method because the Garbage Collector will automatically call it as needed.
  3. GC. GetGenerationReturns the generation of the object passed in as a parameter. This method plays a significant role in debugging and tracking for performance reasons, but has limited role in most applications.
  4. GC. GetTotalMemoryReturns the total allocated memory in the heap. This number is not accurate because of the way the managed heap works, but if you use true as the parameter, you will still get a close approximate value. This method will be recycled once before calculation.

The following is an example of using these methods:
/// <Summary>
/// Displays current GC information
/// </Summary>
/// <Param name = "generation"> The generation to collect </param>
/// <Param name = "waitForGC"> Run GC before calculating usage? </Param>
Public void CollectAndAudit (int generation, bool waitForGC)
{
Int myGeneration = GC. GetGeneration (this );
Long totalMemory = GC. GetTotalMemory (waitForGC );
Console. WriteLine ("I am in generation {0}.", myGeneration );
Console. WriteLine ("Memory before collection {0}.", totalMemory );
GC. Collect (generation );
Console. WriteLine ("Memory after collection {0}.", totalMemory );
}
Author of this ArticleMickey Williams is one of the founders of Codev Technologies. Codev Technologies is an organization engaged in consulting and tools provided by a Windows program developer. He is also a principal member of. NET Experts (http://www.codeguru.com/columns/DotNet/www.dotnetexperts.com), where he teaches. NET Framework courses. He often gave speeches at seminars in the United States and Europe and has written eight books on Windows programming. He is currently being invited by Microsoft press to write "Microsoft Visual C #". You can find him in mw@codevtech.com.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.