arena
import std::alloc::arena; · source
Types
Arena
type struct Arena {
head: Chunk*;
current: Chunk*;
chunk_size: u64;
static new() -> Arena;
static with_chunk_size(chunk_size: u64) -> Arena;
reset(mut &this) -> void;
capacity(&this) -> u64;
used(&this) -> u64;
bump(mut &this, size: u64, align: u64) -> void*;
owns(&this, ptr: void*) -> boolean;
grow(mut &this, ptr: void*, old_size: u64, new_size: u64, align: u64) -> void*;
release(mut &this) -> void;
}
Bump allocation, bulk release. An arena hands out memory by bumping an offset into a chunk. Allocation is O(1), individual deallocation is unsupported, and everything comes back at once through reset (keep the chunks, reuse the space) or drop (return the chunks to the OS).
The shape it fits is "allocate a pile of things with related lifetimes, then throw them away together" — compiler passes, per-request handlers, parse trees. Long-lived caches are not that shape.
import std::alloc::arena;
mut a: Arena = Arena::new();
mut nodes: Array<Node, Arena> = Array::<Node, Arena>::new_in(a);
// ... build the tree ...
a.reset(); // everything above is invalid now; capacity is reused
Repeated reset is where an arena earns its keep — the same memory gets reused instead of round-tripping through the platform allocator.
Each chunk's data buffer is mapped straight from the OS, so releasing it returns the pages immediately and RSS drops at the call, with none of the main-heap retention you get from freeing many small malloc blocks. The mapping is demand-paged, so untouched pages cost nothing and a small arena stays cheap despite the 1 MiB nominal chunk.
Properties
| Property | Type |
|---|---|
head | Chunk* |
current | Chunk* |
chunk_size | u64 |
Constructors
static new() -> Arena;
static new() -> Arena;Create an arena whose chunks are DEFAULT_CHUNK_SIZE bytes each.
static with_chunk_size(chunk_size: u64) -> Arena;
static with_chunk_size(chunk_size: u64) -> Arena;Create an arena with a custom chunk size. Requests larger than chunk_size get their own chunk sized to fit, so the choice is a hint about typical allocation size, not a hard cap.
Methods
reset(mut &this) -> void;
reset(mut &this) -> void;Reset every chunk's high-water mark to zero, making the arena's full capacity available for re-allocation without releasing the underlying chunks back to the system allocator. This is the amortizing power of an arena: repeated reset reuses the same memory instead of round-tripping through malloc/free.
capacity(&this) -> u64;
capacity(&this) -> u64;Total bytes currently held in chunks (including unused tail).
used(&this) -> u64;
used(&this) -> u64;Bytes handed out so far; this is the high-water mark for the arena.
bump(mut &this, size: u64, align: u64) -> void*;
bump(mut &this, size: u64, align: u64) -> void*;Hand out size bytes aligned to align from the arena. Returns null on out-of-memory or a zero-sized request. Marches through the chunk list (reusing chunks emptied by reset) before growing.
owns(&this, ptr: void*) -> boolean;
owns(&this, ptr: void*) -> boolean;True when ptr lies inside any chunk this arena owns. Used by GlobalAlloc's free/realloc routing to recognise arena-backed pointers so they are never handed to libc free. Range-scan of the chunk list (mirrors capacity); a pointer one-past-the-end of a chunk is intentionally excluded.
grow(mut &this, ptr: void*, old_size: u64, new_size: u64, align: u64) -> void*;
grow(mut &this, ptr: void*, old_size: u64, new_size: u64, align: u64) -> void*;Grow (or shrink) a block previously handed out by bump. If ptr is the most-recent allocation in the frontier chunk and that chunk has room for the delta, the block is extended in place and the same pointer returned - this kills realloc-stranding for monotonic single-growers (e.g. a TypeArena.types vector that only ever grows). Otherwise a fresh block is allocated and the old contents copied; the old block is stranded until reset. Returns null on out-of-memory.
release(mut &this) -> void;
release(mut &this) -> void;Release every chunk back to the platform allocator. Invoked by the Drop impl in alloc::arena_alloc; exposed as an inherent method so the drop logic lives next to the allocation logic.
Trait implementations
implement trait Allocator for struct Arena
std::alloc::arena_alloc
implement trait Drop for struct Arena
std::alloc::arena_alloc
Arena implements Allocator, so it drops into any allocator-generic type. Its deallocate is a no-op by design; reallocate tries grow first.
Constants
const DEFAULT_CHUNK_SIZE: u64 = 1048576;type struct Name { ... }
type enum Name { ... }
type trait Name { ... }
type union Name { ... }Begins a type declaration; the keyword that follows says which kind. On its own, type Name = Existing; declares an alias.
type struct Name {
field: Type;
method(&this) -> Ret { ... }
}A value type with named fields and optional methods. Structs live on the stack and are passed by value. Fields are public by default and may carry = default values; methods take their receiver as &this, mut &this, or this.
type struct Arena {
head: Chunk*;
current: Chunk*;
chunk_size: u64;
}Arena: bump allocator with bulk release.
Arena.head: Chunk*type struct Chunk {
data: u8*;
capacity: u64;
offset: u64;
next: Chunk*;
}Arena.current: Chunk*Arena.chunk_size: u64static name(param: Type) -> Ret { ... }A method that belongs to the type rather than an instance, called as Type::name(..). For structs, static new(..) returning a struct literal is the idiomatic constructor.
static Arena::new() -> ArenaCreate an arena whose chunks are DEFAULT_CHUNK_SIZE bytes each.
type struct Arena {
head: Chunk*;
current: Chunk*;
chunk_size: u64;
}Arena: bump allocator with bulk release.
std::alloc::arenastatic Arena::with_chunk_size(chunk_size: u64) -> ArenaCreate an arena with a custom chunk size. Requests larger than chunk_size get their own chunk sized to fit, so the choice is a hint about *typical* allocation size, not a hard cap.
(parameter) chunk_size: u64Arena::reset(mut &this) -> voidReset every chunk's high-water mark to zero, making the arena's full capacity available for re-allocation without releasing the underlying chunks back to the system allocator. This is the amortizing power of an arena: repeated reset reuses the same memory instead of round-tripping through malloc/free.
mut &this
mut &TypeAn exclusive, mutating borrow. As a receiver, mut &this lets the method modify the fields - and callers can see that from the signature alone. As a parameter type, mut &T lets the callee mutate through the reference while the caller keeps ownership.
&this
mut &this
thisThe receiver of a method. Its first parameter declares how the method takes it: &this borrows read-only, mut &this borrows exclusively, and this / mut this move the value in and consume it. In the body, this.field reaches the members.
Arena::capacity(&this) -> u64Total bytes currently held in chunks (including unused tail).
Arena::used(&this) -> u64Bytes handed out so far; this is the high-water mark for the arena.
Arena::bump(mut &this, size: u64, align: u64) -> void*Hand out size bytes aligned to align from the arena. Returns null on out-of-memory or a zero-sized request. Marches through the chunk list (reusing chunks emptied by reset) before growing.
(parameter) size: u64(parameter) align: u64Arena::owns(&this, ptr: void*) -> booleanTrue when ptr lies inside any chunk this arena owns. Used by GlobalAlloc's free/realloc routing to recognise arena-backed pointers so they are never handed to libc free. Range-scan of the chunk list (mirrors capacity); a pointer one-past-the-end of a chunk is intentionally excluded.
(parameter) ptr: void*Arena::grow(mut &this, ptr: void*, old_size: u64, new_size: u64, align: u64) -> void*Grow (or shrink) a block previously handed out by bump. If ptr is the most-recent allocation in the frontier chunk and that chunk has room for the delta, the block is extended in place and the same pointer returned - this kills realloc-stranding for monotonic single-growers (e.g.
(parameter) old_size: u64(parameter) new_size: u64Arena::release(mut &this) -> voidRelease every chunk back to the platform allocator. Invoked by the Drop impl in alloc::arena_alloc; exposed as an inherent method so the drop logic lives next to the allocation logic.
import a::b;
import a::b::{ X, Y };
import a::b as c;
import a::b::*;Brings a module, or selected items from it, into scope. One path per declaration: use the brace form for several items, as to alias, and * for everything public (prefer the brace form; wildcards invite name collisions).
mut name: Type = value;A mutable binding, reassignable after declaration - mutability is opt-in, const is the default. At module level it declares mutable global state. Before & it marks an exclusive reference or receiver instead.
mut a: Arenastatic Arena::new() -> ArenaCreate an arena whose chunks are DEFAULT_CHUNK_SIZE bytes each.
mut nodes: Array<Node, Arena>type struct Array<T, A = GlobalAlloc> where A: Allocator {
ptr: T*;
length: i64;
capacity: i64;
alloc: A;
}Array<T, A>: growable, heap-backed, contiguous sequence.
std::collections::arraystatic Array::new_in(alloc: A) -> Array<T, A>Empty array with a caller-supplied allocator.
std::collections::arraymut a: ArenaArena::reset(mut &this) -> voidReset every chunk's high-water mark to zero, making the arena's full capacity available for re-allocation without releasing the underlying chunks back to the system allocator. This is the amortizing power of an arena: repeated reset reuses the same memory instead of round-tripping through malloc/free.
const NAME: Type = value;At module level, a true compile-time constant, conventionally SCREAMING_SNAKE_CASE. (mut at module level declares mutable global state instead.)
const DEFAULT_CHUNK_SIZE: u64 = 1048576;intrinsic function malloc(size: u64) -> void*Arena.head: Chunk*Arena.current: Chunk*Arena.chunk_size: u64const DEFAULT_CHUNK_SIZE: u64 = 1048576;static Arena::with_chunk_size(chunk_size: u64) -> ArenaCreate an arena with a custom chunk size. Requests larger than chunk_size get their own chunk sized to fit, so the choice is a hint about *typical* allocation size, not a hard cap.
Chunk.capacity: u64Arena::used(&this) -> u64Bytes handed out so far; this is the high-water mark for the arena.
std::alloc::arenaArena::bump(mut &this, size: u64, align: u64) -> void*Hand out size bytes aligned to align from the arena. Returns null on out-of-memory or a zero-sized request. Marches through the chunk list (reusing chunks emptied by reset) before growing.
nullThe null pointer literal, valid in any pointer context - including the primitive string, which is a NUL-terminated u8*. Compare with == null; it is not an Option.
Arena::owns(&this, ptr: void*) -> booleanTrue when ptr lies inside any chunk this arena owns. Used by GlobalAlloc's free/realloc routing to recognise arena-backed pointers so they are never handed to libc free. Range-scan of the chunk list (mirrors capacity); a pointer one-past-the-end of a chunk is intentionally excluded.
type struct GlobalAlloc {}Zero-sized handle to the process-wide allocator. Construct with GlobalAlloc::new(); all instances dispatch through the same underlying backend.
Arena::grow(mut &this, ptr: void*, old_size: u64, new_size: u64, align: u64) -> void*Grow (or shrink) a block previously handed out by bump. If ptr is the most-recent allocation in the frontier chunk and that chunk has room for the delta, the block is extended in place and the same pointer returned - this kills realloc-stranding for monotonic single-growers (e.g.
Arena::release(mut &this) -> voidRelease every chunk back to the platform allocator. Invoked by the Drop impl in alloc::arena_alloc; exposed as an inherent method so the drop logic lives next to the allocation logic.
namespace std::alloc::arena_alloc;Arena trait impls: Allocator and Drop for Arena.
implement struct Name { ... }
implement trait Trait for Type { ... }
implement u64 { ... }Adds methods to a type outside its declaration. implement struct T (or enum, or a bare primitive) opens an inherent block; implement trait Tr for T supplies a trait's methods for one type. Resolution is at compile time - no dynamic dispatch.
implement trait Trait for Type { ... }Introduces a trait implementation: the block supplies, for one concrete type, the method bodies the trait requires.
language referencetype trait Allocator {
allocate(mut &this, layout: Layout) -> Result<NonNull<u8>, AllocError>;
deallocate(mut &this, ptr: NonNull<u8>, layout: Layout) -> void;
reallocate(mut &this, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<u8>, AllocError>;
}Allocator: the trait every heap strategy implements.
std::alloc::allocatorimplement trait Trait for Type { ... }Names the type a trait implementation is for. The block that follows supplies the bodies the trait requires.
language referenceArena::deallocate(mut &this, ptr: NonNull<u8>, block: Layout) -> voidvia trait Allocator
Arenas don't free individuals. This is a no-op; memory comes back at reset or drop.
Arena::reallocate(mut &this, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<u8>, AllocError>via trait Allocator
Grow in place at the frontier when possible (see Arena::grow), else allocate-new + copy.