Arena

Struct Arena 

Source
pub struct Arena<'a> { /* private fields */ }
Expand description

A memory arena for efficient allocation management.

The Arena struct manages a reserved block of virtual memory, enabling fast, contiguous allocations. This structure is particularly useful in scenarios where many small allocations are required, as it minimizes overhead and fragmentation.

§Primary Use-Cases

The Arena is designed for two main allocation patterns:

  1. Long-Lived Allocations: When allocations are expected to persist until the end of the program. This use-case benefits from the arena’s efficient management of memory, avoiding the overhead of frequent deallocations.

  2. Very Short-Lived Allocations: When allocations are needed temporarily, and the allocator is “rewinded” after the allocations are no longer needed. This pattern is ideal for scenarios where large numbers of temporary objects are created and discarded in one go, as it allows for quick cleanup and re-use of the allocated memory.

§Fields

  • current: The active VmRange that tracks the currently allocated range within the reserved memory. Allocations are performed from this range.

  • prev: A secondary VmRange used only in debug mode. This range mirrors the current range and is protected after being decommitted, allowing detection of use-after-free errors. In release mode, this field is not used, and memory protection is disabled to maximize performance.

§Usage

The Arena is initialized with a specified size through the Arena::new function. While the entire size is reserved in virtual memory, physical memory is only committed in page-sized chunks as needed. This design ensures that the memory footprint remains minimal until actual allocations occur.

In debug builds, additional memory protection is enabled to catch potential memory safety issues such as use-after-free, though this comes at the cost of increased memory usage. This feature is automatically disabled in release builds for optimal performance.

Implementations§

Source§

impl<'a> Arena<'a>

Source

pub fn new(size: usize) -> Result<Self, ArenaError>

Initializes a new Arena with the specified size. The size parameter defines the amount of reserved virtual memory. It is recommended to choose a large size since this reservation does not immediately consume physical memory. On a 64-bit system, reserving a few gigabytes is generally acceptable. Physical memory is committed incrementally in page-sized chunks as allocations occur.

In debug mode, decommitted memory is protected to detect use-after-free errors, resulting in double the memory reservation. This protection is disabled in release mode.

Source

pub unsafe fn alloc_raw( &mut self, size: usize, alignment: usize, ) -> Result<&'a mut [u8], ArenaError>

Allocates a raw memory block in the arena.

This function allocates a block of uninitialized memory within the arena. The size and alignment of the block are specified by the caller. The allocated memory is contiguous and may be used for any purpose that requires raw, untyped data.

§Safety

The returned memory is uninitialized, and it is the caller’s responsibility to ensure that the memory is properly initialized before it is used. Failing to do so may result in undefined behavior.

Source

pub unsafe fn alloc_array<T: Sized>( &mut self, count: usize, ) -> Result<&'a mut [T], ArenaError>

Allocates an array of T elements in the arena.

This function allocates uninitialized memory for an array of elements of type T. The number of elements is specified by the count parameter. The memory is contiguous and properly aligned for the type T.

§Safety

The returned array is uninitialized, and it is the caller’s responsibility to initialize the elements before use. Using uninitialized data can lead to undefined behavior. After the arena is rewound, all references to this array become invalid.

Source

pub unsafe fn alloc<T: Sized>(&mut self) -> Result<&'a mut T, ArenaError>

Allocates a single instance of T in the arena.

This function allocates uninitialized memory for a single instance of type T.

§Safety

The returned instance is uninitialized, and the caller must ensure that it is initialized before any use. Uninitialized memory can lead to undefined behavior if accessed.

Source

pub fn alloc_init<T: Default + Sized>( &mut self, ) -> Result<&'a mut T, ArenaError>

Allocates a single instance of T in the arena and initializes it with the default value.

This function allocates memory for a single instance of type T and initializes it using T::default().

Source

pub fn alloc_array_init<T: Default + Sized>( &mut self, count: usize, ) -> Result<&'a mut [T], ArenaError>

Allocates an array of T elements in the arena and initializes them with the default value.

This function allocates memory for an array of elements of type T, and initializes each element using T::default().

Source

pub fn rewind(&mut self)

Rewinds the arena to its initial state.

This method resets the allocation position to the start of the arena without deallocating the memory. After calling rewind, all references to previously allocated memory in the arena should be considered invalid, as any subsequent allocation will overwrite this memory.

§Memory Safety

In debug mode, calling rewind will protect the memory that has been rewound, helping to catch use-after-free bugs. Any access to memory that was allocated before the rewind will result in a crash, as demonstrated in the example below:

use arena_allocator::Arena;

let mut arena = Arena::new(16 * 1024).unwrap();
let t = arena.alloc_init::<u32>().unwrap();
*t = 42;
arena.rewind();
//*t = 43; // This will crash in debug mode
§Usage

This method is particularly useful in scenarios where the arena is used for very short-lived allocations that are discarded en masse. By rewinding the arena, the allocator can quickly reset and re-use the reserved memory without the overhead of deallocation and reallocation.

In release mode, the memory protection mechanism is disabled to ensure optimal performance, but in debug mode, the additional checks help identify improper memory usage patterns.

Trait Implementations§

Source§

impl Drop for Arena<'_>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Arena<'a>

§

impl<'a> RefUnwindSafe for Arena<'a>

§

impl<'a> !Send for Arena<'a>

§

impl<'a> !Sync for Arena<'a>

§

impl<'a> Unpin for Arena<'a>

§

impl<'a> UnwindSafe for Arena<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.