Memory allocations can be classified into two groups: single allocation with resizing, and frequent static size allocation/deallocation. The first is usually seen with vectors while the second is often seen with linked lists and trees. The problem is to create a memory allocation system that attempts to support both of these types of allocations effeciently while also allowing for multi-granularity allocations.
Instead of trying to optimze both allocation schemes at once, it may be more effective to have two allocators that specialize for each type of allocation. In addition, granularity can be handled by allowing for recursive allocators of increasing granularity. As this recursion can be modeled using a tree, the tree allocator will be used for allocation sub-allocators.
Allocator 1: Watermark allocator
This allocator has a very small footprint and amount of time spent on overhead at the cost of being wasteful with space. If kept small, however, the ability to cheaply allocate seems optimal for frequent static allocations.
Allocator 2: Tree allocator
In constrast to the watermark allocator, this allocator has a larger footprint and takes more time for overhead in exchange for smarter allocation and the ability to resize. By organizing allocations and free space in a binary search tree based on the size of the space, the allocations are evenly spaced across the allocatable region. This approach aims to maximize the ability for allocations to be resized in place without requiring a move.
Idea: Rather than always moving the block that is trying to be resized, move the smaller of the two. The exception being that allocators can't be moved.
Note: As this needs to support sub-allocators, it needs to keep track of which are allocators. However, this means that allocations can be done at the top and then trickle down until it finds a space to allocate while creating any new allocators it needs.