Unity / C# value type, reference type, stack, heap, garbage collection GC (theory)

Table of contents

1. The concept of value type and reference type

Value type (value):

Reference type (feference):

Are reference types on the heap and value types on the stack?

2. What is the difference between value types and reference types

3. So what are the heap and the stack? 

the stack

heap

4. Garbage Collector (GC)


Disclaimer: This content comes from various materials and personal summaries

1. The concept of value type and reference type

Value type (value):

int float bool  struct  enumeration (enum) etc.

Reference type (feference):

The class array is a reference, even if the element is a value type (int[] is a reference). The delegate (delegate) is a reference. The interface (interface) is a reference, but it can be implemented with a value type, etc.

Are reference types on the heap and value types on the stack?

  1. There is nothing wrong with referring to instances of types that are always on the heap, but variables and method parameters declared inside methods are on the stack. And the value of an instance variable is always stored where the instance itself is stored. For example, if there is an int variable in a class, although it is a value type, it is on the heap.
  2. A variable of reference type contains two storage locations: the storage location directly associated with the variable, and the storage location referenced by the value stored in the variable.
  3. For the storage location directly associated with the variable and the storage location associated with the value type variable, there is no difference in their storage location, that is, the reference itself will be the same as the value type. If the variable exists for a short time, it will be allocated in the temporary storage pool of the stack. .

2. What is the difference between value types and reference types

  1. After the assignment, the difference between whether the two values ​​change synchronously, the value type is assigned, and they are independent. The reference type becomes one after assignment, and when one side changes, the other side also changes. 

3. So what are the heap and the stack? 

  • the stack

The stack is a special space reserved in memory, which is specially used to store small, short-term data values, which will be automatically released once they exceed the function, so it is called a stack. Like the stack in the data structure, the memory stack also has push and pop.
All declared local variables (such as int a;) will be placed on the stack, and their loading and unloading will be handled when the function is called. That is to say, the variables have been defined on the stack before the program runs. These function calls are expanded and contracted through the so-called call stack. When the call stack processing is completed for the current function, it jumps back to the call point before the call stack and continues to execute the remaining content from the position it left before. The location of previous memory allocations is always known, and no memory cleanup operations need to be performed because new memory allocations overwrite old data, so the stack is relatively efficient.
The total size of the stack is usually small, on the order of megabytes (MB). When allocating more space than the stack can support, it may cause a stack overflow, which occurs when executing a large number of call stacks (such as infinite loops) or when there are a large number of local variables, but most of the time, despite the relatively small size of the stack, But rarely cause stack overflow.

  • heap

The heap represents all other memory space and is used for most memory allocations**. Since we want most memory allocations to hold longer than the current function call, they cannot be allocated on the stack, because the stack will overwrite the results generated before and after the method execution ends. Because data types are sometimes too large, or need to be kept outside the function, there is a heap. Physically there is no difference between the heap and the stack, they are both just memory spaces that contain data bytes that exist in RAM. The operating system requests and saves these data bytes. The difference is when, where and how they are used.
In native code, such as languages ​​written in C++, these memory allocations are handled manually, and it is our responsibility to ensure that all memory blocks are allocated correctly, and to explicitly free memory when not needed. Otherwise, it is easy to cause memory leaks until the memory is insufficient and the program crashes.
In managed languages, memory release is automatically handled by the garbage collector. During the initialization of the Unity program, the Mono platform applies for a string of memory from the operating system to generate a heap memory space (usually called a managed heap) for use by C# code. This heap space starts out relatively small, less than 1MB, but grows as script code requires new chunks of memory. If Unity no longer needs it, then that space can be shrunk by releasing it back to the OS.

4. Garbage Collector (GC)

The Garbage Collector (GC) has an important job of making sure that no more managed memory is used than needed, and memory that is no longer needed is automatically reclaimed. In other words, GC will participate in the creation and destruction of objects. For example: If you create a GameObject and then destroy it, the GC will mark the memory space used by the object so that this memory can be reclaimed at a later time. Note that memory recovery is not real-time, but memory is only recovered when it is not needed.

The GC in the version of Mono used by Unity is a tracing GC that uses a mark-and-sweep strategy. The algorithm is divided into two phases:

Each allocated object is tracked by an extra bit of data. This data bit indicates whether the object is marked. These flags are set to false, indicating that it has not been flagged. When the collection process starts, it marks all objects that are still accessible to the program by setting the object's flag Alive to true. Accessible objects are either direct references (such as static or local variables on the stack), or indirect references through fields (member variables) of other directly or indirectly accessible objects. In theory, all unreferenced objects should be recycled.
The second phase involves iterating over such references (which the GC will track throughout the life of the program) and deciding based on its marking state whether it should be recycled. If an object is not marked, it is considered a candidate for collection. This phase will directly skip the objects that have been marked, but will reset them to false before the next garbage collection scan to complete a new round of marking.
When the execution of the second stage ends, all unmarked objects will be formally reclaimed to free up space, and then revisit the accident request for creating objects. If the GC has released enough space, allocate memory in the newly freed space and returned to the caller. If the released space is not enough, you can only apply for more managed heaps from the system.

In fact, the GC maintains a list of all objects in memory, while the application maintains another separate list containing only some of them. As soon as the program is done with the object, it simply forgets it exists and removes it from the list, regardless of whether the object needs to be recycled or not. In other words, the work of garbage collection is done independently by the GC, and the program only needs to maintain its own object list.

Games have high performance requirements. To improve efficiency, GC can be called when scenes are switched or resources are not used frequently.

Guess you like

Origin blog.csdn.net/q1295006114/article/details/130915670