[Memory Fragmentation/Memory Hole]

Memory Fragmentation / Memory Holes

Memory Fragmentation: 

After the program runs for a long time, due to the non-stop malloc/free operation, although there is no memory leak, the memory space occupied by the program is getting larger and larger, and sometimes the malloc application fails, which is caused by memory fragmentation.



 

cause: 

The memory that is not allocated by mmap can only be released from the top of the heap. Even if the memory in the middle part is released by free, it is still occupied by the current program and is not completely released to the heap, so it cannot be used by other programs. Only after the memory at the top of the heap is also released can this area be merged into a large space.

 

solution: 

There is no ultimate perfect solution to this problem.

 

Use the reuse of memory space as much as possible to reduce the operation of frequently requesting a large number of small memory blocks.

Unified planning for the dynamic memory required by the program. The application operation of the memory that needs to be occupied for a long time is performed when the program is initialized after the program is started, and the application operation of the memory that does not need to be occupied for a long time is executed later. This way the top of the heap can be released as soon as possible. 

However, it should be noted that memory allocation is not necessarily sequential, that is, the memory address applied for later is not necessarily larger than the original memory address, and a previously released area may be used.

 

 

There is a difference between memory growth caused by memory holes and memory leaks:

A memory leak is that the allocated memory is not released. If you are doing the same operation multiple times, the memory used by the process should keep growing at the same rate.

A memory hole is the memory that has been applied for and released because it is not at the top of the heap and cannot be returned to the system, but this memory can still be used by the process itself, so if you do the same operation multiple times, the memory used by the process should stay at a horizontal line , not much growth, or not much growth.

Programmers can judge based on this phenomenon whether there is a memory leak or a memory hole in your process.

In the actual situation, there are many phenomena of memory holes. According to my observation, in the heap, there are more memory fragments than memory holes. Therefore, programmers only need to understand the concept of memory holes. When applying for memory allocation, they can follow the principle of proximity. Only allocate memory when needed, and release it immediately when it is not needed. There is no need to strictly pursue the order of application and release, nor can it be done.



 

 

The Linux kernel can only free physical memory by shrinking linear memory regions.

The first method is to use the system call brk to change the top address of the heap to release the memory.

advantage:

The algorithm is simple, the system calls are few, and the efficiency is high.

shortcoming:

The physical pages below the top of the heap cannot be released in time even if they are free.

 

 

Method 2: By splitting the linear area of ​​the corresponding heap, the physical pages in the middle are released.

advantage:

Memory below the top of the heap can be freed immediately.

shortcoming:

The algorithm is complex, involving the splitting and merging of linear regions, which may cause the process heap segment to form multiple discrete small memory spaces, which has a great impact on the performance of the process.

 

Based on the above factors, the linux kernel chooses to expand and release memory space by adjusting the top of the heap.

It also determines that as long as there is still memory in use at the top of the heap, no matter how much memory is released below the top of the heap, it will not be released, which is what we often call memory holes.

In addition to extending the heap top address through brk, we also mentioned another memory allocation method, mmap. When libc is processing a large block of memory allocation, it will call mmap to allocate a block of address space; when releasing, it will directly call unmmap to release the memory space, so the application and release of this large block of memory allocation will not There is a memory hole problem.

You can reduce the probability of memory holes by using mmap to allocate memory thresholds. The tradeoff is that more system calls may be used, reducing the performance of the process.

In order to eliminate the impact of memory holes, it is required that when applying and releasing memory, we must strictly follow the principle of proximity, and release the memory at the top address of the heap first. The order of application and release of controllable memory is very difficult; in addition, due to the impact of memory fragmentation, the memory address obtained each time the application has a certain degree of randomness, and the memory applied for later does not necessarily mean that it is in the

Top of the heap; this is simply Mission impossible.

As a programmer, I'm very frustrated, I can't do anything, I call free to release memory, but it doesn't necessarily return to the system, I can't fully control the behavior of my program, who can guarantee that there is no such a block at the top of the heap What about the memory being used? This also gives a lot of programmers an excuse. During the test, the memory usage of our program grows. When asking them to check, they go to

I used to say, "I have freed all the memory. This is caused by a memory hole, and there is nothing I can do about it.". The boss has nothing to say, empty memory has become our nightmare.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326311312&siteId=291194637