Dlmalloc 2.8.6 source code (5), dlmalloc2.8.6

Source: Internet
Author: User

Dlmalloc 2.8.6 source code (5), dlmalloc2.8.6

This article was originally created by vector03. For more information, see the source.

Email Address: mmzsmm@163.com, welcome to discuss.

 

 

3. allocation and implementation

This topic describes the algorithm and implementation of dlmalloc allocation. due to the existence of multiple mspaces, dlmalloc uses two sets of APIs. A set of default mspaces starting with the dl prefix, such as dlmalloc and dlrealloc. if a custom mspace is created, Apis starting with mspace, such as mspace_malloc and mspace_realloc, are used. however, the two APIs are consistent in the basic algorithm. we will introduce the default API as the main object.

3.1 algorithm Overview

In fact, despite the complexity of dlmalloc, the core algorithm is very simple and can be easily understood if there is a foundation in the previous chapter.

The core allocation algorithm summarizes the five sentences for small request and large request (note that the allocation request size here is the size after align and padding processing ), corresponding to small request (<256 bytes ),

1. first, search for the bin size corresponding to the allocation request and a larger bin level. If yes, return. Otherwise, go to the next step. select the two binning boxes because they are the closest to the allocation target size and the remaining parts cannot be a separate chunk (originally called remainderless chunk ).

2. If the dv size is sufficient, cut the dv chunk. Otherwise, proceed to the next step.

3. Search for all bins (including small bins and tree bins), find the minimum chunk that can meet the requirements, cut, and specify the remaining part as the dv. Otherwise, go to the next step.

4. If the top chunk meets the requirements, cut the top; otherwise, go to the next step.

5. Get the memory from the system and use it.

Corresponding to large request,

1. find the minimum available tchunk from the tree bins. If it is more suitable than dv (closer to the target size), use this chunk. if the remaining part exceeds the minimum allocable chunk, cut it. otherwise, proceed to the next step.

2. If dv meets the requirements and is more suitable than chunk in any bin, use dv. Otherwise, proceed to the next step.

3. If top meets requirements, use top. Otherwise, proceed to the next step.

4. If the allocation request is greater than the threshold value of mmap_threshold, it will be allocated directly through mmap; otherwise, the next step will be taken.

5. Get the memory from the system and use it.

In terms of type, dlmalloc belongs to the best-fit type distributor, but Doug Lea has made many optimizations on this basis. in essence, it is based on the idea of making the best use of things to select a suitable free chunk. Only when it cannot be met first, dlmalloc will make further selection through dv and top, this minimizes the generation of internal fragments. in addition, the existence of dv and top can effectively reduce external fragments.

If the external request is too large, dlmalloc is not allocated after the system memory is obtained first, instead, it tends to be obtained directly through mmap. the reason is that the free chunk in top may be unable to be released because of the alloced chunk of the adjacent high address. if dlmalloc requests a large amount of memory from the system, even if it is free by the application, it may also cause them to reside in the top space for a long time due to auto trmming failure. the advantage of direct mmap is that these huge chunks can be returned to the system at any time, as long as the application decides not to use them.

Below is a more detailed code analysis,

It is basically easy to understand, and I will explain it in some areas below,

1. line5491. If lock is used here, check whether some global parameters are initialized. these parameters are saved in the global variable named mparams. The type is malloc_params, which contains the magic of the cross-check, the current system page size, the set granularity size, and the mmap threshold, trimming threshold and default mspace parameters. and uses magic as the parameter initialization flag.

2. line4595, PREACTION and POSTACTION appear in pairs, that is, locking and unlocking. because it is platform-related, specific implementations are required for different systems. it can be seen from this that dlmalloc is still relatively simple in the allocation design under multi-thread conditions, and focuses on the implementation of allocation algorithms in a single thread.

3. line4619, here is a delete operation on the first node of the double link list, and if the list is empty, update small map. note that in order to increase the list processing speed, dlmalloc designed the header node. Therefore, this first chunk is not a header node, but a previous node. as mentioned in the previous chapter, we can see these advantages through the specific implementation here. B Refers to the list header node, and P refers to the node to be deleted.


 

4. line4663 is the process of replacing dv. If the old dv still exists, it will be sent back to the binning system for management, and the new chunk will be replaced. M indicates the mstate, P indicates the successor dv, and S indicates the successor dv.

Here, insert_small_chunk is the reverse operation of the previous deletion, which is implemented as follows,

During insertion, the small map is maintained.

3.2 tmalloc_small

Tmalloc_small is a subfunction allocated to small chunk in tree bins. the core allocation algorithm 3 used for small requests, that is, searches from tree bins when remainderless and dv cannot meet and the remaining small bins do not have free chunk.

The code itself is easy to understand. The source code is annotated as follows,

Two notes,

1. Line4537: Find the least DST node through the macro leftmost_child. The macro is defined as follows,

The traversal of the smallest node is involved. we know that for BST, the root node has a strict sorting relationship with the left and right subtree. Therefore, the minimum node to be searched is to step from the root node to the left subtree, the left subtree is always stopped by null.

However, as described in section 2.2.5, DST is not a sorting tree, and the root node and the subtree cannot determine the size relationship. In contrast, it is more difficult to obtain the minimum node. however, it can be determined that, at the same level, the Child Tree nodes closer to the left are smaller, so we can roughly define the scope of the occurrence of the smallest node, as shown below,

Colors are used to mark the leftmost node of each level (not limited to left or right subtree). Although it is impossible to determine which node is the smallest node, but it certainly appears in the path from A to E. therefore, the DST search path is to start from the root node and step all the way to the left subtree. If the left subtree is empty, it will turn to the right subtree and the left and right subtree will always be empty and stop. in other words, go along the leftmost edge of the entire DST tree,

In this regard, I think it should be the biggest defect of DST, because in any case, the number of traversal times is related to the height of the tree, and the smallest node may appear in the position C, however, you must complete each comparison before making the final decision. fortunately, for systems with size_t equal to 4 bytes, the tree height is only 32 at most. in any case, this is much faster than linear search.

2. line4551, related to the delete operation of DST. since the unlink_large_chunk macro code is long, you should first describe the Node Deletion algorithm. basically, Doug Lea's DST deletion algorithm is divided into three steps,

Step 1: Determine whether the node X to be deleted has a brother node of the same size. If yes, simply remove it from the double-stranded table and re-connect the linked list .,

Step 2: If node X is located at only one node, You need to select a successor node R to replace the position of X vacancy, and ensure the DST nature. DST is also a type of prefix tree. Therefore, it is easy to increase the level of a subtree node, but it is complicated to decrease the level. for example, if the subtree node prefix is 0101, it can be upgraded to 010, but if it is downgraded to 0101x... X must refer to other sub-trees .,

If we select R as the successor node, then the left subtree node L of the original node X will change its level. in this case, you must refer to the subtree R to find a suitable insertion point for L. if R is complicated internally, this process will be relatively long.

Therefore, Doug Lea chose the right-most leaf node as the successor node of X. since it is a leaf node, you only need to simply raise the level. The level and position of other subtree nodes do not change, so the above problem is bypassed. when right-most is selected, dlmalloc searches for the best-fit Node Based on the left-most path. In most cases, the number of left subtree nodes is less than that of the right subtree. to balance left and right Subtrees and reduce the height of Subtrees, right-most is more suitable ,,

Find the right-most node R of subtree X and use it to replace the position of X vacancy. We can see that the positions of node L and other subtree nodes have not changed. at the same time, changing the R position balances the left-to-right subtree to make DST more balanced as a whole.

Step 3: it is clear that you only need to reconnect the successor node to the parent node of the original X and the left and right subtree nodes.

The source code of the entire process is described as follows,

3.3 tmalloc_large

This function is a subfunction that assigns a large request to tree bins. it is slightly different from tmalloc_small. large request is not a minimum node, but a best-fit node, that is, a minimum node greater than or equal to the expected value.

The basic algorithm is as follows,

1. the base value is retrieved Based on the allocation request size nb as the key value, and two points are recorded. one is to record The nearest candidate node v, and The other records The nearest untraversed right subtree node rst (The deepest untaken right subtree ). if a chunk of the same size is found, return immediately.

2. if it has been traversed to the bottom layer of the subtree, the rst subtree node of the record is returned. From this position, the left-most traversal is performed, here, it is the same as finding the smallest subtree node in tmalloc_small.

3. If no available node is found, find the minimum available binning from treemap and find it from the available binning.

4. If dv is more suitable than candidate node v, 0 is returned directly. Otherwise, the candidate node is cut and the payload is returned.

The search process in the same bin,

In A bin, search for the best-fit node in the order from A to F. where the A-D belongs to the Base Value retrieval, with the nb prefix as the key value, while the E-F is retrieved according to left-most, because E subtree is the smallest subtree in the current bin larger than the target value, you only need to find the minimum node. it can also be seen from this that this algorithm is essentially very simple, that is, first search for the closest target node according to the prefix. If not, the extended range will be searched in the smallest subtree greater than the target value, it is not found in the nearest bigger bin until it is found.

The code is annotated as follows,

Line4465, Line4480, and Line4490 are actually bit-by-bit test operations on the nb mask for Base Value retrieval.

The macro is shown as follows,

It seems complicated. In fact, in addition to the highest and second most effective bits, the subsequent bit is moved to the msb end, and one bit is retrieved for detection every cycle, as shown in,

I> 1 is not easy to understand. review the description of tree bins index addressing in section 2.2.4. Here is the inverse computer_tree_index operation. the result is the bid with the highest valid bits. the reason for the decrease of 2 is that the highest valid and second high valid bits are used to calculate the bin number, so the key value is not counted. the mask obtained after displacement will be moved to the hidden position again during detection, and extracted to determine whether to step toward the left or right subtree. throughout the cycle, the mask is moved left to ensure that the traversal continues until the bottom layer of the subtree node is reached.

In fact, this macro Doug Lea is a little troublesome. This operation can get the same result by adding 2 to the CLZ command. I guess the reason Doug Lea does not write this way may be to minimize the differences between different platforms, or simply he is too lazy to write four implementations separately.

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.