Some in-depth discussions on CLR memory management [Part II] From artech)

Source: Internet
Author: User
Tags mscorlib

In the previous article, we mainly discuss assembly and appdomain topics, this section focuses on two different Assembly Loading Methods: exclusive mode and sharing mode (neutral domain mode), and process-based string resident. This article focuses on the memory allocation during hosting object creation and the collection of large objects (Lo: Large Object). We hope you will be able to point it out in time.

1. Start with type and instance

In the object-oriented world, types and instances are two core elements. Regardless of the type and instance, the related information such as loading to the memory corresponds to one or more contiguous or discontinuous memories. How does one allocate the type and instance memory? The object is a combination of "state" and "behavior", so from. from the perspective of Net Framework, it only has two types of members-fields and methods (actually there are nested types). The former indicates the State, and the latter indicates the behavior. The type is the description of the metadata, and the instance is a single individual that meets the description of the metadata. All instances of the same type have the same behavior, which can be distinguished by different status values. Therefore, an instance in the memory (the instance mentioned in this Article refers to an instance of the reference type) represents the field value, while a type in the memory represents the metadata of the type member structure. Many people know that when we create an object, CLR will open up a continuous memory space in the GC heap to save the field values. So what type information is stored in that memory?

In fact, the type information is stored on another heap, which is called the loader heap ). Each application domain has its own loader heap, which includes the common application domain we created and the three special application domains mentioned in the previous article: system Program domain, shared program domain, and default program domain. If the GC heap is an instance container, the loader heap based on the application domain is a type container. CLR adopts the "load on demand, timely compilation" operating mechanism. When a type is used for the first time, CLR tries to load the type. If the corresponding program of this type is not independently loaded to the application domain, or is not loaded to the shared application domain in the form of a neutral domain, it loads the assembly in the appropriate way (Here we assume that the exclusively loaded method is used ). Then, load the type used to the loader heap of the application domain.

The loader heap maintains all types of records used since the application domain was created. They correspond to a special object named method table ). When the program executes a method for the first time, the CLR locates the entry in the method table and obtains relevant information for JIT compilation. Therefore, if an entry of a type in the method table in the loader heap is executed at least once, it will point to a machine instruction after JIT compilation.

Ii. instance memory allocation is not limited to GC heap

So far, we know that the types and instances are allocated to the application domain-based loader heap and GC heap respectively. Is the CLR memory allocation limited to these two heaps? Of course not. In addition to the "two heaps" and the default process heap, there are two additional "two heaps". One is the JIT heap that stores the JIT compiled machine commands ), the other is a large object heap (Loh: Large Object heap) dedicated for "large objects ). It reflects these different "heaps" that CLR mainly maintains ".

For large object heap, we will talk about it later in this article. here we need to first understand what type of object the CLR considers as a "large object ". When we instantiate an object, if the object is larger than or equal to 85,000 bytes (this object is generally an array, and the object is generally not so large ), CLR will regard it as a "large object" and put it in LOH; otherwise, it will be placed in the GC heap. Here, you need to note that the GC as a garbage collector is not only limited to the collection of objects in the GC heap, but the collection of objects in Loh is under the jurisdiction of GC. So in a sense, you can think of the previously mentioned GC heap as Soh (small object heap) or "narrow GC Heap ", the general GC heap is interpreted as Soh + LOH.

Iii. instance type reference

An instance is a type instance, and the instance and its corresponding type need to maintain a connection. Reflected in the memory, it is assumed that the objects allocated in the GC heap or LOH have a reference to the method table of this type located in the loader heap. Instance type references are maintained by a special object -- typehandle. For example, in the following simple Object Instantiation code, I instantiate four objects: string "ABC", system. object object, custom bar object, and byte array with 85000 elements.

   1: string strInstance         = "ABC";
   2: object objectInstance      = new object();
   3: Bar barInstance            = new Bar()
   4: byte[] largeObjInstance    = new byte[85000];

After the above program is executed, there will be a relationship like the next one in the memory around the four objects and types of Instantiation information. The leftmost is the four variables in the ready-made call stack. For strinstance of the string type, the total string is allocated to the system program domain due to the string resident mechanism described in the previous article; objectinstance and barinstance of the object and bar types are allocated to the GC heap because they are small objects smaller than 85000 bytes. Objectinstance points to System in the shared program domain through typehandle. the method table corresponding to the objhect type (because the mscorlib Assembly defining this type is loaded as a neutral field ), the bar-based method table pointed to by the typehandle of the barinstance is located in the default program domain (because the program domain is loaded exclusively by default ). Largeobjinstance, a byte array with 85000 elements, is a large object and is directly allocated to LOH. Largeobjinstance typehandle points to system. method table of the byte [] type. The system. the byte [] type is also defined in the mscorlib assembly, so this method table also exists in the loader heap of the shared program domain.

4. How to recycle objects in Loh

Readers who know GC should know that CLR adopts the "Generation"-based garbage collection mechanism. I personally think it is a very accurate term, which fully reflects the designer's meaning of "different objects have different lifecycles. All objects are divided into three generations, namely, G0, G1, and G2, which actually represents three consecutive memory blocks. The higher the generation score, the longer the time. The lower the generation score, the higher the frequency of being swept (GC recovery. We will talk about the aging-based garbage collection mechanism. Our focus is on how GC recycles LOH objects.

So far, except for the size of objects in the Loh and GC heap, we do not seem to think of any difference between them. In fact, putting large objects in LOH aims to implement a special recycling mechanism for them. With regard to garbage collection, we should have the cognition that the cost of collection is basically a "positive" relationship with the object size. The larger the object, the larger the recycling cost. Therefore, we cannot frequently recycle large objects. In fact, CLR treats LOH objects as objects of the highest age. That is to say, LOH recycling is carried out together with G2 in the GC heap. In other words, when the remaining space of G2 or Loh is lower than a certain limit, garbage collection is triggered for them. We can verify Loh's garbage collection mechanism through a very simple program.

   1: class Program
   2: {
   3:     static WeakReference SmallObjRef;
   4:     static WeakReference LargeObjRef;
   5:  
   6:     static void Main(string[] args)
   7:     {
   8:         SetValues();
   9:         GC.Collect(0);
  10:         Console.WriteLine("GC.Collect(0)");
  11:         Console.WriteLine("SmallObjRef.Target == null? {0}", SmallObjRef.Target == null);
  12:         Console.WriteLine("LargeObjRef.Target == null? {0}\n", LargeObjRef.Target == null);
  13:  
  14:         GC.Collect(1);
  15:         Console.WriteLine("GC.Collect(1)");
  16:         Console.WriteLine("LargeObjRef.Target == null? {0}\n", LargeObjRef.Target == null);
  17:  
  18:         GC.Collect(2);
  19:         Console.WriteLine("GC.Collect(2)");
  20:         Console.WriteLine("LargeObjRef.Target == null? {0}\n", LargeObjRef.Target == null);
  21:     }
  22:  
  23:     static void SetValues()
  24:     {
  25:         SmallObjRef = new WeakReference(new byte[84000]);
  26:         LargeObjRef = new WeakReference(new byte[85000]);
  27:     }    
  28: }

Output result:

   1: GC.Collect(0)
   2: SmallObjRef.Target == null? True
   3: LargeObjRef.Target == null? False
   4:  
   5: GC.Collect(1)
   6: LargeObjRef.Target == null? False
   7:  
   8: GC.Collect(2)
   9: LargeObjRef.Target == null? True

In the code above, I have created two weakreference objects whose targets are set to byte [84000] and byte [85000] respectively. According to the above definition of "Large Object", the latter is a large object, and the former is not. Then, three times of garbage collection for G0, G1, and G2 were carried out, and we found that "small objects" were not removed after garbage collection for G0; the "Large Object" will survive until the garbage collection for G2 is executed.

Author: artech
Source: http://artech.cnblogs.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.