. NET memory base (using the memory experience type, passing parameters, and packing box),. net packing

Source: Internet
Author: User
Tags unpack

. NET memory base (using the memory experience type, passing parameters, and packing box),. net packing

This essay was inspired by the connection between CLR Via C # (Third edition) Chapter 4 4.4 Runtime

I. Areas of Memory Allocation

1. Thread Stack

The Value Type of the local variable and the pointer (or reference) of the reference type in the local variable are allocated to this region (a part of the memory of the reference type is allocated to this region ).

This area is controlled by the system and is not controlled by the garbage collector. After the method is executed, local variables are automatically released (the reference type only releases the pointer, but not the data pointed to by the pointer ).

Stack execution efficiency is high, but the capacity is limited.

2. GC Heap (recycle Heap)

It is used to allocate a small object (reference type). If the instance size of the reference type is smaller than 85000 bytes, it will be allocated to this region.

3. LOH (Large Object Heap)

A large object (reference type) with more than 85000 bytes will be allocated to this region.

The difference between LOH and GC Heap is that when memory is allocated or recycled, the Garbage Collector may compress the GC Heap, but LOH will not be compressed, but will only be recycled during garbage collection.

 

 

Ii. stack frame)

Stack callback is the data structure that implements function calls.Logically, stack callback is a function execution environment (context), including function parameters, return addresses, and function local variables.

Note: The above "return address" is not the return value of the function, but the position of the code to be executed by the CPU after the function is called.

For more information, see call stack in Wikipedia.

 

3. Shallow copy and deep copy (Clone, or Clone)

The shortest copy and deep copy are two methods of memory copy. During parameter passing, the memory copy usually occurs and is a shortest copy. For example, the following code and two parameters are two shortest copies.

Public void Test1 () {string name = "test1"; int size = 1; Test2 (name, size); // two shallow copies} public void Test2 (string pName, int pSize ){}

Shows the memory results before and after the shortest copy:

For the value type (for example, int), the shortest COPY Copies the specific value in the stack.

For the reference type (for example, string), the copy operation copies the stack reference, the address in the managed heap to which the new reference points, or the original address.

 

The difference between deep copy and shallow copy is that it processes the data (that is, the object) in the heap.:

Shortest copyOnly copies the reference in the stack, does not copy the object in the stack, and the new reference points to the original object.

Deep copyCopies the references in the stack and creates new objects in the stack, the attribute value of the new object "may" come from the original object (because you need to write additional code to implement deep copy in C,

That is, the ICloneable interface is implemented, and the results of deep copy are uncertain. However, we recommend that you avoid using this interface as much as possible). The new reference address points to the new object. Therefore, deep copy is only applicable to reference types,

It does not make much sense for value types.

 

Iv. Demo

If the first three items are used as the foundation, the Demo is the text.

The following classes have been defined in advance:

    public class Data     {        public string Name;        public int Size;    }

Assume that the code is about to call the Test1 function:

        public void Test1()        {            string name = "test1";            int size = 1;            Data data = new Data() { Name = "test1", Size = 1 };            Test2(name, size, data);            object obj = size;            int temp = (int)obj;        }        public void Test2(string pName, int pSize, Data pData)        {            pName = "test2";            pSize = 2;            pData.Name = "test2";            pData.Size = 2;                        pData = new Data() { Name = "test3", Size = 3 };                    }

The details of the thread stack and the managed Stack are shown in Figure 1 ):

 

1,Start to call the Test1 function. A stack frame will be pushed to the stack ).

Stack metadata contains three parts of data:

1) function parameters. Of course, the Test1 function does not have any parameters.

2) return address. In the Test1 function, taking the current Code environment as an example, this address has no practical significance and is not described.

3) function local variables. All local variables in the Test1 function will be pushed to the stack. The following five local variables are pushed into the stack:

String name, int32 size, Data data, object obj, int32 temp. (Of course, there are actually six local variables, and the sixth is automatically generated by the compiler. I will explain them at the end of the article .)

The memory result is shown in figure 2 ):

 

2,Next, run the code of the Test1 function, assign a value to the name, assign a value to the size, and assign a value to the data. The memory results will be shown in Figure 3 ):

InRed LineAndVariables generated by the compilerIt will be explained at the end of the essay.

 

3,Next, we will call the Test2 function. At this time, we will also press a stack token into the stack.

Stack metadata contains three parts of data:

1) function parameters. The Test2 function has three parameters. The three parameters are all shortest copies.

2) return address, which is the location of the next line (or the next command) where the Test2 function code is called. That is:

Obj = size; // The object obj; operation has been completed when the Test1 function is called and pushed into the stack.

After the function is called, the above code is executed.

3) The local variable of the function. The compiler will automatically generate a variable (which will be explained at the end of the article)

Therefore, the memory result is shown in Figure 4 ):

The two orange lines are the results of parameter shortest.

 

4,The memory result is shown in Figure 5 before the Test1 function is returned after the Test2 function is executed ):

Red LineIt will be explained at the end of the essay.

Yellow LineNote that string is a special reference type, and its external representation is consistent with the value type, but it is essentially a reference type. Because of the immutability of the string, each value is assigned to the string.

Will generate a new object (if the new object does not exist), resulting in a yellow line.

Light Green LineI think there should be no problem with this line.

 

5,After the Test2 function is called, the Code returns to the location shown in the address returned by the Test2 function stack consumer. In this process, the consumer of the Test2 function stack is displayed, as shown in figure 6 ):

The unused objects in the managed heap will be automatically recycled by GC, and the time for collection is uncertain.

 

6,As can be seen from 3, next we will execute the obj = size; operation --PackingIt can be understood literally as follows: the value type is loaded into the box of the reference type.

The procedure is as follows:

1) First, create a new object in the heap. (This operation reduces the performance of the packing operation)

2) copy the size value to the object.

3) Finally, point the reference of obj to the newly created object.

The final result is shown in figure 7 ):

 

7,Last operation --Unpack.

Packing is to load the value type into the box of the reference type. During this process, object creation and memory replication occur.

However, unpacking is not so complicated, and there is no similar "splitting" process, it only reads the value type from the object (the most time-consuming operation should be the operation to find the memory address where the value type is located), and its performance is much better than packing.

The final result is shown in figure 8 ):

 

 

V. Syntactic sugar-object initializer

The following two code snippets are completely equivalent:

Data temp = new Data (); // The variable Name automatically generated by the compiler is not necessarily temp. Name = "test1"; temp. Size = 1; data = temp;
       data = new Data() { Name = "test1", Size = 1 }; 

The second writing method can be seen as a shorthand. during compilation, the compiler converts the code in the second writing method into the first writing method. Therefore, the new syntax features of the object initiator, C #3.0,

It is completely a syntactic sugar, and CLR does not play any role.

When you see this, think about the aboveRed LineEverything can be solved.

 


Net packing and unpacking principles

The previous answer was wrong. I understood the incorrect question.

Packing -- convert the value type to the reference type:
Int I = 1;
Object o = I;
-- Here, we will first open up four bytes of stack space to store variable I, and then open up variable o, which is a 4-byte pointer, this pointer is used to point to the first address for storing data in the heap. In this case, we need to open the space required by variable I into the heap, and then let the o pointer point to the first address in the newly opened heap. This is packing.

Unpack -- convert the reference type to the value type:
Object o = 1;
Int I = (int) o;
-- The operation here is the opposite of turning. It will first open up the space of pointer o in the stack, and then point to the first address of the opened data space required by data 1 in the heap. Then, The binning operation of strong conversion will revalue the data in the heap (not copy it) to the stack-that is, re-open the strong Conversion Type in the stack (here it is int) memory space required in the stack, and the data o in the heap is assigned. Here, we also need to determine whether o can be correctly converted to an int (not to see InvalidCastException often, which is the result of an exception thrown after judgment ). So unpacking consumes more performance.

Summary:
Packing and unpacking are aimed at converting the space data of the CPU in the memory, which involves operations such as memory development, re-assignment, conversion, and judgment, such packing and unpacking operations will be performed on multiple data in a group. Therefore, try to reduce the number of binning operations.

Net packing and unpacking

First time:
Object 0 = v; equivalent to Object 0 = (Object) v;

Second:
Console. WriteLine (v + ","); equivalent to Console. WriteLine (string) v + ",");

Third time:
(Int) o.

Related Article

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.