Introduction to Stack Allocation
Based on the OxCaml documentation at oxcaml.org.
In OCaml, values are normally allocated on the garbage-collected heap. OxCaml can instead allocate values on the stack, which offers two performance advantages: the same few hot cache lines are constantly reused (lower cache footprint), and stack allocations never trigger a GC -- making them safe for zero-alloc, low-latency code.
The stack_ keyword
Use stack_ before an allocation to force it onto the stack:
The keyword works shallowly -- it only affects the immediately following allocation. Most types can be stack-allocated: tuples, records, variants, closures, and boxed numbers.
Regions and escaping
Stack-allocated values live in a region (usually a function body) and must not escape it. The type-checker enforces this. Try uncommenting the last line to see the error:
Local parameters
To pass a stack-allocated value to a function, the function must promise not to let it escape. This is done with @ local:
A function with @ local parameters can be called with either stack- or heap-allocated values -- the annotation only constrains the function's implementation, not its callers. Here sum_pair computes a global int result from a local tuple, so the result can safely escape.
let mutable for loop variables
OxCaml's let mutable provides mutable local variables that are always stack-allocated, avoiding any heap allocation:
Compare this with the traditional approach using a ref (which allocates on the heap):
Returning local values with exclave_
The exclave_ keyword lets a function allocate in its caller's region, enabling the caller to stack-allocate the result:
Inference
In practice, you rarely need to write stack_ explicitly. The compiler infers stack allocation whenever possible:
Without the @ local annotation on f, the pair would need to be heap- allocated since the compiler couldn't prove f won't capture it.
The global_ field annotation
When you need to extract a value from a stack-allocated record and return it, mark the field global_:
The global_ annotation means the field's contents are always on the heap, even when the record itself is stack-allocated.