The Problems On Free List Allocator in phobos and My Improve Ideas

xiaoyu malyjacob926 at gmail.com
Thu Nov 14 02:39:44 UTC 2024


I recently tried to use the free-list allocator in the standard 
library, but encountered some problems during use.Then I 
inspected this part of the code and found some other problems.

The pronlems are below:

1. When allocations are frequent and the size fluctuates greatly, 
it is easy to degenerate into only a proxy of the parent 
allocator and cannot make good use of free memory blocks.

2. When the memory size to be allocated is not in the `[min, 
max]` range, it instead requests the parent allocator to 
allocate, but this is unreasonable. This unreasonable request 
should be rejected and `null` should be returned.

3. The `allocateZeroed` method does not necessarily depend on the 
parent allocator's `allocateZeroed`.

4. It is not reasonable to directly forward the `expand` and 
`reallocate` methods of parent allocator.In fact, `expand` does 
not depend on the `expand` of parent allocator, and this also 
isolates the possibility of `alignedExpand` and 
`alignedReallocate`.

5. It cannot perfectly cope with situations where it does not 
exclusively onws the parent allocator.For example, when the 
free-list allocator does not exclusively onws the parent 
allocator, method `owns` may regard blocks allocated by other 
allocators that rely on the same parent allocator as being 
allocated by itself. Allocator's `deallocate` and `deallocateAll` 
have the same problem.


My ideas for improvement are as follows:

1. Add a field called `volum` for `Node`, indicating the memory 
size allocated by this block excluding `Node`, and the memory 
occupied by `Node` will not be overwritten. That is to say, when 
the block where `Node` is located is allocated, the memory 
occupied by `Node` itself will not be overwritten.

2. The free-list allocator maintains two linked lists internally, 
one representing the free memory block linked list, and the other 
representing the allocated memory block linked list. The free 
memory block linked list is sorted and inserted according to the 
size of the corresponding `volum` from small to large.

3. When an allocation request occurs, it will first try to search 
in the free memory block linked list. Because this linked list is 
sorted, it can allocate the memory block with the most suitable 
size relatively quickly. If a suitable memory block is found, it 
will be allocated and put the `Node` corresponding to this memory 
block at the beginning of the allocated-list, otherwise forward 
the request to the parent, construct a `Node`, and put this 
`Node` at the beginning of the allocated-list. If the adaptive 
mode is turned on, there will be some additional optimization 
operations during this period.

4. When choosing to `deallocate` a memory block, it will first 
check whether the block is being managed on the allocated-list 
(this is also the implementation logic of `owns`). If it is 
`true`, the block will be removed and inserted into the 
free-list. This operation It does not really return the memory 
block to the parent. The same is true for deallocateAll. This 
method inserts all memory blocks managed by allocated-list into 
free-list for future allocation requests.

5. When this allocator is destroyed, the memory blocks managed by 
the two linked lists will be returned to the parent. Of course, 
you can also manually reduce the length of the free-list.

6. Then based on the above ideas, I provide `alignedAllocate`, 
`alignedExpand` and `alignedRellocate`, `resolveInternalPointer`.


This is just a general idea. For details, you can check out the 
code I improved on `https://github.com/malyjacob/free-list`. 
There are comments and explanations in it. Of course, I only 
improved the non-thread safe parts. If possible, the thread safe 
version can also adopt this improvement idea.


More information about the Digitalmars-d mailing list