What is memory management

Memory management is the process of controlling and coordinating applications’ access to the computer’s memory. The process is complex and, for us, a black box.

When our application runs on an operating system, it accesses the computer’s memory (RAM) to perform the following functions:

  1. Run the bytecode (code) that needs to be executed
  2. Stores the data needed to run the program
  3. The runtime environment the program needs to run

The heap and stack are used to store the data that a program needs when it runs.

The stack (stack)

As the name implies, it is a kind of advanced after the structure, take a reference to eat plate and put.

Matryoshka dolls. I can’t help it

The characteristics of the stack

  • Due to the nature of the first out, data processing on the stack has a very good speed, because only from the top of the stack and out of the stack, simple and clear.
  • However, the data stored in the stack must be of a finite size with a deterministic lifetime.
  • The function creates and pushes an explicit stack during execution, and stores all the data in the function during execution. This is called a stack frame. Personal feelings can be interpreted as a snapshot of the currently executing function.
  • Multithreaded applications have multiple stacks.
  • The stack is automatically allocated or released by the operating system.
  • Common types stored on the stack are: local variables (value types, primitive types, constants), Pointers, and functions
  • Remember that stack Overflow error you occasionally encountered? This is because stack size is limited compared to the heap. This is true of most generic languages.

Heap (heap)

The heap is often used for dynamic memory allocation, and programs need to use Pointers to find data in the heap.

The characteristics of the pile

  • Not as efficient as stacks, but can store more data
  • Can store data of indeterminate size, such as runtime determination
  • Multiple threads in an application share heap data
  • The heap is manually operated and can be tricky to manage, causing problems such as memory leaks, so many languages have GC mechanisms
  • Common types stored in the heap are global variables, reference types, and other complex data structures
  • That’s why you get problems like out of memory errors because the user misallocates or doesn’t destroy
  • There’s actually no limit to the size of the data we allocate to the heap, and in theory you can allocate an infinite amount of data. Of course you have to allocate that much memory to your application. -_ –

The difference between memory stack and data structure stack

memory The data structure
The heap New A reference or address to an object stored in the stack refers to the object’s real data stored in the heap. Allocated and reclaimed by the programmer It’s a complete binary tree
The stack Stores the parameters, local variables, and return values of the run method. It is automatically distributed and recycled by the system. Is a continuous storage data structure, characterized by the storage of data first out

The importance of memory management

Unlike hard disks, memory is limited in size and often not very large. So, if you continue to consume memory indefinitely without releasing unused memory, you will run out of memory and even crash the operating system… Therefore, many languages provide automatic memory management for this purpose. And since the stack is controlled by the system, the automatic memory management we will discuss next is primarily the heap.

Writing this, I want to say, I do not recognize the word heap…

Different memory management methods

Because nowadays language developers don’t want to burden users with memory management (or don’t trust them to handle it). , so the design of automatic memory management. And many languages have devised ways to automatically manage memory for developers to choose from. Here are some of them.

Manual memory management

Languages do not manage memory by default, such as C and C++, which provide malloc, Realloc, Calloc, free, etc., but this is not for everyone.

GC (Garbage collection)

Managing heap memory by freeing unwanted memory space is one of the most common methods of automatic memory management in current programming, but a lot of processing can lead to thread congestion, so use fragmentation time. The languages that use gc are JVM, JavaScript, C#, Golang, OCaml, and ruby.

Mark & Sweep GC

Also known as tracing GC. There are two phases: the first phase flags data that should be active, and the next phase frees data that is not referenced. For example, the JVM, C#, RubyJavaScript, and Golang all take this approach. V8 also uses Reference Counting GC, which can also be used in C and C++ as external libraries.

Reference counting GC

Reference counting memory management. A number is used to indicate whether the current data is recyclable or not. The number changes based on references and lost references, and is recycled when it is 0. But this does not handle circular references.

Resource Acquisition is Initialization (RAII)

It was proposed by Bjarne Stroustrup, the father of c++. In this type of memory management, the object’s memory allocation is related to its declaration cycle. Its core is to bind resources to the life cycle of the object. The object is created to obtain resources, and the object is destroyed to release resources. Under the guidance of RAII, C++ takes the underlying resource management problem to a higher level of object lifecycle management. Introduced in C++, Ada and Rust are also used.

Automatic Reference Counting(ARC)

Automatic reference counting. Is an automatic memory management mechanism for Apple objective-C programs. Similar to reference counting, but instead of running at specific intervals, the hold and release commands are inserted into the code and are automatically triggered when the count reaches zero without program pause. Of course ARC still can’t handle circular references. Requires the developer to use certain keywords to handle it.

Ownership

Ownership is Rust’s breakthrough feature. It enables Rust to be completely memory safe and efficient while avoiding garbage collection. Ownership in Rust language is the core of Rust language, and the reason why Rust language is called a secure system-level programming language is determined by this feature.

Rust guide

summary

So far, we’ve covered memory management briefly. Each language has a specific mechanism, and all have different algorithms to achieve different goals. Let’s move on to V8.

V8 engine

V8 improves performance by compiling JavaScript into machine code before running, rather than bytecode or interpreting it. V8 is written in C++ and can be embedded in any C++ application.

V8 Memory structure

First, let’s take a look at what the V8 memory structure looks like:

Since JS is single-threaded, Node still provides a single-threaded environment for each JS environment. If you use it on the server side, it provides a process for each service. In V8 programs, the application is always represented by the memory allocated. This memory becomes the resident set. As shown above.

Heap memory in V8

This is where objects and dynamic data are stored, this is the largest area of memory, and this is where THE GC works. However, not all heap memory can be GC, only the new and old generations are managed by GC. The heap can be further subdivided as follows:

  • Cenozoic space: A place where newly generated data lives, often ephemeral. This space is split in two and then managed by Scavenger(Minor GC). More on that later. You can control the size of new generation space with V8 flags such as –max_semi_space_size or –min_semi_space_size
  • Old generation space: Data that has survived at least two rounds of Minor GC from the New generation space, which is managed by the Major GC(Mark-sweep & Mark-Compact), described later. Space size can be controlled by –initial_old_space_size or –max_old_space_size.
    1. Old pointer space: a surviving object that contains Pointers to other objects
    2. Old Data space: a surviving object that contains only data.
  • Large object space: This is an object larger than the size of the space. Large objects are not processed by GC.
  • Code space: This is jIT-compiled code. This is in addition to theLarge object spaceThe only executable space that is not allocated and executed in.
  • Map space: Stores cells and maps. Each area stores elements of the same size. The structure is simple.

V8 Memory management anatomy

Now that we’ve looked at the spatial organization of memory, let’s look at how important memory is when a program executes.

Less BB, look at the code:

class Employee {
    constructor(name, salary, sales) {
        this.name = name;
        this.salary = salary;
        this.sales = sales; }}const BONUS_PERCENTAGE = 10;

function getBonusPercentage(salary) {
    const percentage = (salary * BONUS_PERCENTAGE) / 100;
    return percentage;
}

function findEmployeeBonus(salary, noOfSales) {
    const bonusPercentage = getBonusPercentage(salary);
    const bonus = bonusPercentage * noOfSales;
    return bonus;
}

let john = new Employee("John".5000.5);
john.bonus = findEmployeeBonus(john.salary, john.sales);
console.log(john.bonus);
Copy the code

Click here to see a display of memory space during code execution

In plain English: the global is stored on the stack as a snapshot of the following, and a snapshot is placed on the stack for each function call, including the local variables, parameters, and return values of the function. Basic types are stored in the stack, and objects, complex types, or reference types are stored in the heap. Any function call is pushed at the top of the stack. Once the main process has completed all tasks, objects in the heap are not referenced and isolated.

As our program runs, there is more and more data in the heap, and since it is unattended and the stack is automatically managed by the system, there is no need to worry about it. So, to manage heap space, garbage collection comes in.

V8 Memory management: GC

Now that we know how V8 allocates memory, let’s look at how V8 manages heap space.

As a simple example, V8 frees isolated objects, which are generally not directly or indirectly referenced, to make room for new objects.

Therefore, the V8 garbage collection mechanism stands for: Reclaim unused memory for V8 reuse.

The specific implementation is as follows:

Minor GC (Scavenger)

Dustman GC mainly manages the new generation space to ensure the compact and clean space of the new generation. All objects are allocated to the Cenozoic space, which is relatively small. The value ranges from 1M to 8M and can be controlled by commands.

The GC flow looks something like this: The new generation space consists of two equally divided Spaces, to-space and from-space, which can be understood as phases (currently in use and currently unused) rather than names. The Minor GC is triggered when there is no more memory currently in use. For example, when there is no more space in the current use and a new space object is added, the Minor GC switches the currently unused space to the current use and then collates the data from the previously full space into the new, empty current use, depending on whether it survives. What is alive is put away, and what is not alive is thrown away. And when moving live data, it is packed tightly to avoid wasting space. Finally, the unallocated space object is allocated to the new current use. As more unallocated space comes in, the above process is repeated, but if a piece of data survives more than twice, it is thrown into the old generation space. To ensure the new generation of space.

The above process can be summed up with an example: Xiao Ming went to the Internet cafe, the first time to go, there is a position, directly on the machine. No room, have to wait for the boss to clean down to the time of the machine, and then on the machine. This kind of time is generally no card (not alive). The second time, the same procedure. The NTH time, Xiao Ming also got a card (survival). If Xiao Ming’s card expires, he will be inactivated.

The above mentioned process, must refer to this flow chart!!

Major GC(Mark-Sweep & Mark-Compact)

This GC is mainly responsible for the compactness and cleaning of the old generation space. This GC is triggered when V8 knows there is no more space in the old generation space. The scavenger GC above is perfect for small data, but not for large data. A better approach is the mark-scanning-compact algorithm, which, as the name suggests, has three steps.

Not much explanation. Look at the picture for yourself.

conclusion

The memory stack was introduced, and the data structure stack was compared. After that, several GC methods and V8 implementation are briefly analyzed. More in-depth content welcome to exchange, learn from each other.

Finally, you are very welcome to pay attention to my nuggets. The latest content will be pushed first in the future, which is convenient for learning and communication.

reference

memory-management

V8 memory analysis

Memory and data stack