Author: Edison Chou Source: Blog Park publish time: 2014-09-03 15:59 read: 318 recommendations: 2 original link [favorites]
Original Shivprasad Koirala
English Original: Six important. NET Concepts:stack, heap, value types, reference types, boxing, and unboxing
I. Overview
This article explains six important concepts: heap, stack, value type, reference type, boxing, and unpacking. This article begins by explaining the changes that occur within the system after you define a variable, and then shifts the focus to the storage duo: Heap and Stack. After that, we'll look at value types and reference types, and give an explanation of the important basics of both types.
This article uses a simple code to demonstrate the performance impact of the boxing and unpacking process, so please read it carefully.
Second, what happens when you declare a variable?
When you're in a. NET application, it allocates some memory blocks in RAM when a variable is defined. This memory has three things: the name of the variable , the data type of the variable , and the value of the variable .
It simply illustrates what happens in memory, but what type of memory your variables will be assigned to depends on the data type. There are two types of memory that can be allocated in. NET: stacks and heaps . In the next few sections, we will try to understand the two types of storage in detail.
Three, the storage of the two male: heap and stack
To understand stacks and heaps, let's use the following code to understand what's going on behind the scenes.
public void Method1 () { //Line 1 int i=4; Line 2 int y=2; Line 3 Class1 cls1 = new Class1 ();}
The code is only three lines, and now we can do it one line at a time to see how the inside is executed.
- Line 1: When this row is executed, the compiler allocates a small chunk of memory on the stack. Stack will be in charge of tracking your application for running memory needs
- Line 2: The second step will now be performed. Just like the name of the stack, it overlays a small chunk of memory allocation here at the top of the memory allocation that was just the first step. You can think of a stack as a room or box that is stacked up. In the stack, the allocation and release of data is done through LIFO (last in First out), which is the advanced logic rule. In other words, the data item that is first entered in the stack is likely to end up in the stack.
- Line 3: in the third row, we created an object. When this line is executed,. NET creates a pointer in the stack, and the actual object is stored in a memory area called the heap. The heap does not monitor running memory, it is just a bunch of objects that can be accessed at any time. Unlike stacks, the heap is used for dynamic memory allocation.
- Another important point to note here is that the reference pointer of the object is allocated on the stack. For example: statement statement Class1 CLS1; Instead of allocating memory for an instance of Class1, it simply creates a reference pointer on the stack for the variable CLS1 (and assigns its default position to null). Only when it encounters the new keyword does it allocate memory on the heap for the object.
- when you leave this Method1 method (the Fun): Now the execution control statement begins to leave the method body, and all the memory space allocated for the variable on the stack is cleared. In other words, all variables related to type int in the example above will be stacked one by one from the stack in the form of "LIFO" LIFO.
- It is important to note that at this point it does not release the blocks of memory in the heap, and the blocks of memory in the heap will be cleaned up by the garbage collector.
Now many of our developer friends must be curious about why there are two different types of storage? Why can't we allocate all the memory blocks to only one type of storage?
If you watch carefully enough, the primitive data types are not complex, they just save values like ' int i = 0
. Object data types are complex and they reference other objects or other primitive data types. In other words, they hold references to multiple other values and these values must be stored in memory one by one. The object type requires dynamic memory and the primitive type requires static memory. If the requirement is dynamic memory, then it allocates memory on the heap, instead, it is allocated on the stack.
Iv. value types and reference types
Now that we know the concept of stacks and heaps, it's time to understand the concepts of value types and reference types. A value type saves both data and memory in the same location, and a reference type has a pointer to the actual memory area.
Through, we can see a type of shaping data called I, whose value is assigned to another shaped data type named J. Their values are stored on the stack.
When we assign a value of type int to another value of type int, it actually creates a completely different copy . In other words, if you change the value of one of these, the other does not change. As a result, these kinds of data types are referred to as "value types".
When we create an object and assign the object to another object, they point to each other in the same area of memory as the code snippet shows. So when we assign obj to obj1, they point to the same area in the heap. In other words, if we change any of them at this point, the other will be affected, which also explains why they are referred to as "reference types".
Five, which are value types, and which are reference types?
In. NET, whether a variable is stored in a stack or in a heap depends entirely on the data type to which it belongs. For example: ' String ' or ' Object ' belongs to the reference type, while the other. NET primitive data type is assigned to the stack. is shown in detail in the. NET preset types, which are value types and which are reference types.
Six, packing and unpacking
Now, you have a lot of theoretical foundation. Now it is time to understand the use of the above knowledge in practical programming. One of the biggest implications of the application is understanding the performance consumption problems that occur when data is moved from the stack to the heap, and vice versa.
Consider the following code snippet, when we convert a value type to a reference type, the data is moved from the stack to the heap. Conversely, when we convert a reference type to a value type, the data is also moved from the heap to the stack.
Whether moving from the stack to the heap or moving from the heap to the stack inevitably has some impact on the system performance.
As a result, two words turned out: The process of converting data from a value type to a reference type is called boxing , and the process of converting from a reference type to a value type is "unboxing."
If you compile the above code and view it in ILDASM(An IL anti-compilation Tool), you will find out what boxing and unboxing are like in the IL code. The IL code generated after the sample code is compiled is shown.
Seven, packing and unpacking performance issues
In order to figure out what the performance impact of boxing and unpacking will be, we cycle through the two function methods shown in 10,000 times respectively. There is a boxing operation in the first method, and the other is not. We use a Stopwatch object to monitor the time consumption.
The method with the boxing operation took 3542 milliseconds to complete, and the method without the boxing operation took only 2477 milliseconds, a full 1 seconds. Also, this value increases as the number of cycles increases. In other words, we should try to avoid packing and unpacking operations. In a project, if you need boxing and boxing, carefully consider whether it is absolutely essential to the operation, if not, then try not to.
Although the above code snippet does not show a unboxing operation, the same effect applies to unpacking. You can write code to implement unpacking and test its time consumption through stopwatch.
. NET six important concepts: stacks, heaps, value types, reference types, boxing and unpacking (GO)