Expand description
Bump-pointer arena allocator for ZK proving workloads.
§Two-allocator model
ZkAllocator is a façade over two allocators selected per call:
- Arena: one
mmapregion split into per-thread slabs. Allocation bumps a thread-local pointer;deallocis a no-op.begin_phase()resets every slab so the next phase reuses the same physical pages. - System:
std::alloc::System(glibc on Linux). Used for everything the arena shouldn’t hold:- any allocation when no phase is active;
- any allocation smaller than
min_arena_bytes()even during a phase (size-routing — keeps small library bookkeeping outside the arena); - oversize allocations or threads that arrived after slabs were claimed
(
overflow_stats()reports these); - regrowth via
reallocof a pointer that was already in System (sticky-System routing — System allocations don’t migrate to arena on growth, even if the new size exceeds the size-routing threshold).
§Phase scoping contract
begin_phase() activates the arena and resets every slab. end_phase()
deactivates the arena. Allocations made during phase N must not be held
past begin_phase() of phase N+1: that call recycles the slab, and the
next allocation at the same offset will silently overwrite the retained
bytes.
Practical rules:
- Drop or
clone()arena-allocated values before the phase ends. - Use
PhaseGuard/phaseto ensureend_phaseruns even on panic — without it, an unwinding phase leaves the arena active and subsequent “post-phase” allocations land in arena territory. - Keep long-lived state (thread pools, channels, registries, caches) constructed outside any active phase so it lives in System.
§Realloc migration: prevented
realloc checks whether the input pointer lies in the arena region.
If it does, growth goes through the normal arena path (subject to
size-routing). If it does not, growth stays in System via
System::realloc — preventing the failure mode where a System-backed
Vec silently migrates into the arena on push.
§Configuration
ZK_ALLOC_SLAB_GB— per-thread slab size in GiB (default8).ZK_ALLOC_MIN_BYTES— size-routing threshold in bytes (default4096). Set to0to send every active-phase allocation to the arena.
§Example
ⓘ
use zk_alloc::ZkAllocator;
#[global_allocator]
static ALLOC: ZkAllocator = ZkAllocator;
loop {
let proof = zk_alloc::phase(|| heavy_work()); // arena on inside
let output = proof.clone(); // detach into System
submit(output);
}Structs§
- Phase
Guard - RAII guard for an arena phase. Calls
begin_phase()on construction andend_phase()on drop — including during panic unwinding. Use this in place of pairedbegin_phase()/end_phase()calls when the phase body can panic, to avoid leaving the arena active across the unwind. - ZkAllocator
Functions§
- begin_
phase - Activates the arena and resets every thread’s slab. All allocations until the next
end_phase()go to the arena; the previous phase’s data is overwritten in place. - end_
phase - Deactivates the arena. New allocations go to the system allocator; existing arena
pointers stay valid until the next
begin_phase()resets the slabs. - min_
arena_ bytes - Returns the minimum allocation size routed through the arena. Allocations smaller than this go to System even during active phases.
- overflow_
stats - Returns (overflow_count, overflow_bytes) — allocations that fell through to System because they exceeded the slab or arrived after all slabs were claimed.
- phase
- Runs
finside a phase. Equivalent to constructing aPhaseGuard, runningf, and dropping the guard. Panics infpropagate, but the phase is guaranteed to end before unwinding leaves this function. - reset_
overflow_ stats - slab_
size - Returns the per-thread slab size in bytes. Zero before the first
begin_phase().