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:
-
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.
-
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 activeVmRangethat tracks the currently allocated range within the reserved memory. Allocations are performed from this range. -
prev: A secondaryVmRangeused only in debug mode. This range mirrors thecurrentrange 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>
impl<'a> Arena<'a>
Sourcepub fn new(size: usize) -> Result<Self, ArenaError>
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.
Sourcepub unsafe fn alloc_raw(
&mut self,
size: usize,
alignment: usize,
) -> Result<&'a mut [u8], ArenaError>
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.
Sourcepub unsafe fn alloc_array<T: Sized>(
&mut self,
count: usize,
) -> Result<&'a mut [T], ArenaError>
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.
Sourcepub unsafe fn alloc<T: Sized>(&mut self) -> Result<&'a mut T, ArenaError>
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.
Sourcepub fn alloc_init<T: Default + Sized>(
&mut self,
) -> Result<&'a mut T, ArenaError>
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().
Sourcepub fn alloc_array_init<T: Default + Sized>(
&mut self,
count: usize,
) -> Result<&'a mut [T], ArenaError>
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().
Sourcepub fn rewind(&mut self)
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.