pub struct BumpAllocator { /* private fields */ }
Expand description

A suballocator which can allocate dynamically, but can only free all allocations at once.

With bump allocation, the used up space increases linearly as allocations are made and allocations can never be freed individually, which is why this algorithm is also called linear allocation. It is also known as arena allocation.

BumpAllocators are best suited for very short-lived (say a few frames at best) resources that need to be allocated often (say each frame), to really take advantage of the performance gains. For creating long-lived allocations, FreeListAllocator is best suited. The way you would typically use this allocator is to have one for each frame in flight. At the start of a frame, you reset it and allocate your resources with it. You write to the resources, render with them, and drop them at the end of the frame.

See also the Suballocator implementation.

Algorithm

What happens is that every time you make an allocation, you receive one with an offset corresponding to the free start within the region, and then the free start is bumped, so that following allocations wouldn’t alias it. As you can imagine, this is extremely fast, because it doesn’t need to keep a free-list. It only needs to do a few additions and comparisons. But beware, fast is about all this is. It is horribly memory inefficient when used wrong, and is very susceptible to memory leaks.

Once you know that you are done with the allocations, meaning you know they have all been dropped, you can safely reset the allocator using the try_reset method as long as the allocator is not shared between threads. It is hard to safely reset a bump allocator that is used concurrently. In such a scenario it’s best not to reset it at all and instead drop it once it reaches the end of the region, freeing the region to a higher level in the hierarchy once all threads have dropped their reference to the allocator. This is one of the reasons you are generally advised to use one BumpAllocator per thread if you can.

Efficiency

Allocation is O(1), and so is resetting the allocator (freeing all allocations). Allocation is always lock-free, and most of the time even wait-free. The only case in which it is not wait-free is if a lot of allocations are made concurrently, which results in CPU-level contention. Therefore, if you for example need to allocate a lot of buffers each frame from multiple threads, you might get better performance by using one BumpAllocator per thread.

The reason synchronization can be avoided entirely is that the created allocations can be dropped without needing to talk back to the allocator to free anything. The other allocation algorithms all have a free-list which needs to be modified once an allocation is dropped. Since Vulkano’s buffers and images are Sync, that means that even if the allocator only allocates from one thread, it can still be used to free from multiple threads.

Implementations

Creates a new BumpAllocator for the given region.

Panics

Resets the free start back to the beginning of the region if there are no other strong references to the allocator.

Resets the free-start to the beginning of the region without checking if there are other strong references to the allocator.

This could be useful if you cloned the Arc yourself, and can guarantee that no allocations currently hold a reference to it.

As a safe alternative, you can let the Arc do all the work. Simply drop it once it reaches the end of the region. After all threads do that, the region will be freed to the next level up the hierarchy. If you only use the allocator on one thread and need shared ownership, you can use Rc<RefCell<Arc<BumpAllocator>>> together with try_reset for a safe alternative as well.

Safety
  • All allocations made with the allocator must have been dropped.

Trait Implementations

Formats the value using the given formatter. Read more
Returns the device that owns Self.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.