Essential API

This page covers the core functions you'll use 99% of the time. For the complete API reference, see Full API.

Array Acquisition

acquire!(pool, T, dims...)

The primary function. Returns Array{T,N} for most T. For T === Bit, returns a native BitVector/BitArray{N}.

@with_pool pool begin
    v = acquire!(pool, Float64, 100)        # 1D: Array{Float64,1} (Vector)
    m = acquire!(pool, Float64, 10, 10)     # 2D: Array{Float64,2} (Matrix)
    t = acquire!(pool, Int64, 2, 3, 4)      # 3D: Array{Int64,3}
    mask = acquire!(pool, Bit, 1000)        # BitVector (bit-packed)
end

Always use acquire! by default. Returns native Array{T,N} that works seamlessly with BLAS/LAPACK, FFI/ccall, and any function expecting Array; Bit masks are bit-packed and optimized for boolean-kernel operations (count, any, all, etc.). acquire_array! is an alias for acquire!.

acquire_view!(pool, T, dims...)

Returns a lightweight view into pool storage (SubArray for 1D, ReshapedArray for N-D). This is the old acquire! behavior from v0.2.x. Use when you want zero-allocation views and don't need a native Array:

@with_pool pool begin
    v = acquire_view!(pool, Float64, 100)      # SubArray{Float64,1}
    m = acquire_view!(pool, Float64, 10, 10)   # ReshapedArray{Float64,2}
end
`Bit` behavior

For T === Bit, acquire_view! returns native BitVector/BitArray{N} (same as acquire!).

Convenience Functions

Zero-initialized arrays:

@with_pool pool begin
    z = zeros!(pool, Float64, 10, 10)   # All zeros
    o = ones!(pool, Float64, 100)       # All ones
end

Match existing array properties:

@with_pool pool begin
    A = acquire!(pool, Float64, 50, 50)
    B = similar!(pool, A)                # Same type and size as A
    C = similar!(pool, A, ComplexF64)    # Same size, different type
end

Reshaping with reshape!

Reshape an existing array using the pool's wrapper cache. The result shares memory with the original — mutations are visible in both:

@with_pool pool function process_grid(data, nx, ny)
    M = reshape!(pool, data, nx, ny)   # 1D → 2D, shares memory with data
    col_sums = zeros!(pool, Float64, ny)
    for j in 1:ny, i in 1:nx
        col_sums[j] += M[i, j]
    end
    return sum(col_sums)
end

On Julia 1.12+, cross-dimensional reshapes are zero-allocation after warmup via setfield!-based wrapper reuse. On Julia ≤1.11, falls back to Base.reshape.

DimensionMismatch

prod(dims) must equal length(A), otherwise a DimensionMismatch is thrown.

Custom Initialization with fill!

For values other than 0 or 1, use Julia's built-in fill!:

@with_pool pool begin
    v = acquire!(pool, Float64, 100)
    fill!(v, 3.14)              # Fill with pi

    m = acquire!(pool, Int64, 10, 10)
    fill!(m, -1)                # Fill with sentinel value
end

This pattern works because pool arrays share underlying storage with the pool.

Pool Management

reset!(pool)

Resets all active-slot counters to zero but keeps every allocated buffer for reuse. Use it to recover a clean pool state (e.g. after code acquired without a matching rewind!) without paying reallocation costs:

# Mark all slots inactive, but keep buffers warm for the next batch
reset!(get_task_local_pool())

trim!(pool; force_gc=false)

Releases the pool's references to all inactive retained buffers (those already freed by rewind!/scope exit), while preserving the active arrays still in use. It does not selectively keep "warm" buffers — at top level, after a normal rewind! (where n_active == 0), every reusable buffer is released. The only guarantee is that arrays still active on the call stack are left untouched.

# After a scope rewinds, drop retained-but-unused buffers
summary = trim!(get_task_local_pool())
@show summary.slots_released summary.estimated_bytes_released

# To release everything reusable, mark top-level slots inactive first:
reset!(pool); trim!(pool)

# force_gc=true additionally runs GC.gc() (no guarantee of immediate OS/VRAM return)
trim!(pool; force_gc = true)

estimated_bytes_released is capacity-aware (it counts buffers even when runtime checks shrank them to length 0). It estimates detached storage; it is not a guarantee that RSS/VRAM dropped immediately — that depends on the GC.

Julia version

Actual reclamation requires Julia 1.12+. On older Julia, trim! is a defined no-op (returns a zero summary, warns once) so dependent packages stay portable across the full supported Julia range.

empty!(pool)

Drops all buffers (active and inactive) and resets the pool to its initial state. The most aggressive reclamation; invalidates any arrays still in use.

pooling_enabled(pool)

Check if pooling is active (returns false for DisabledPool):

@maybe_with_pool pool begin
    if pooling_enabled(pool)
        println("Using pool")
    else
        println("Pooling disabled")
    end
end

Quick Reference

FunctionReturnsAllocationUse Case
acquire!(pool, T, dims...)Array{T,N}0 bytesDefault choice
acquire_array!(pool, T, dims...)Array{T,N}0 bytesAlias for acquire!
acquire_view!(pool, T, dims...)View type0 bytesLightweight views
zeros!(pool, [T,] dims...)Array{T,N}0 bytesZero-initialized
ones!(pool, [T,] dims...)Array{T,N}0 bytesOne-initialized
similar!(pool, A)Array{T,N}0 bytesMatch existing array
reshape!(pool, A, dims...)Reshaped array0 bytes (1.12+)Reshape sharing memory
reset!(pool)pool-Reset counters, keep buffers for reuse
trim!(pool; force_gc=false)summary-Release inactive buffers, keep active
empty!(pool)pool-Release all memory, reset state
pooling_enabled(pool)Bool-Check pool status

See Also