Skip to main content

Crate zk_alloc

Crate zk_alloc 

Source
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 mmap region split into per-thread slabs. Allocation bumps a thread-local pointer; dealloc is 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 realloc of 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:

  1. Drop or clone() arena-allocated values before the phase ends.
  2. Use PhaseGuard / phase to ensure end_phase runs even on panic — without it, an unwinding phase leaves the arena active and subsequent “post-phase” allocations land in arena territory.
  3. 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 (default 8).
  • ZK_ALLOC_MIN_BYTES — size-routing threshold in bytes (default 4096). Set to 0 to 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§

PhaseGuard
RAII guard for an arena phase. Calls begin_phase() on construction and end_phase() on drop — including during panic unwinding. Use this in place of paired begin_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 f inside a phase. Equivalent to constructing a PhaseGuard, running f, and dropping the guard. Panics in f propagate, 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().