pub struct Arena { /* private fields */ }Expand description
An arena allocator.
If you have never used an arena allocator before, think of it as allocating objects on the stack, but the stack is really big. Each time you allocate, memory gets pushed at the end of the stack, each time you deallocate, memory gets popped from the end of the stack.
One reason you’d want to use this is obviously performance: It’s very simple and so it’s also very fast, >10x faster than your system allocator.
However, modern allocators such as mimalloc are just as fast, so why not use them?
Because their performance comes at the cost of binary size and we can’t have that.
The biggest benefit though is that it sometimes massively simplifies lifetime and memory management. This can best be seen by this project’s UI code, which uses an arena to allocate a tree of UI nodes. This is infamously difficult to do in Rust, but not so when you got an arena allocator: All nodes have the same lifetime, so you can just use references.
Do not push objects into the arena that require destructors. Destructors are not executed. Use a pool allocator for that.
Implementations§
Source§impl Arena
impl Arena
pub const fn empty() -> Self
pub fn new(capacity: usize) -> Result<Self>
pub fn offset(&self) -> usize
Sourcepub unsafe fn reset(&self, to: usize)
pub unsafe fn reset(&self, to: usize)
“Deallocates” the memory in the arena down to the given offset.
§Safety
Obviously, this is GIGA UNSAFE. It runs no destructors and does not check whether the offset is valid. You better take care when using this function.
pub fn alloc_uninit<T>(&self) -> &mut MaybeUninit<T>
pub fn alloc_uninit_slice<T>(&self, count: usize) -> &mut [MaybeUninit<T>]
Trait Implementations§
Source§impl Allocator for Arena
impl Allocator for Arena
Source§fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
allocator_api)Source§fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
allocator_api)allocate, but also ensures that the returned memory is zero-initialized. Read moreSource§unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
allocator_api)ptr. Read moreSource§unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
allocator_api)Source§unsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow_zeroed( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
allocator_api)grow, but also ensures that the new contents are set to zero before being
returned. Read more