newsfilter.io
Tutorial, Other

OCaml Locals Save Allocations | OCaml Unboxed

  • Objective: Demonstrate how the local keyword in a specialized OCaml compiler (Jane Street's branch) reduces memory allocation and garbage collection overhead by restricting value lifetimes to specific regions.
  • Region Definition: In this compiler model, both function bodies and loop bodies define distinct "regions" where local values are guaranteed not to escape.
  • Benchmark Program: A test loop iterates 10,000 times, generating a random-length list of integers and counting elements divisible by five.
  • Baseline Allocation: Without optimizations, the standard implementation (using list.init and list.iter) allocates approximately 204,000 words, verified via ocamlopt and ocamlopt flags (-v 1024).
  • Escape Analysis Failure: Simply annotating a variable as local fails if the function consuming it (e.g., standard list.iter) allows the value to escape, as the standard library does not yet support locality annotations.
  • Custom Implementation Requirement: To achieve locality, custom implementations of iter and init are required because they must explicitly enforce that arguments and return values do not escape their defining regions.
  • Type Inference Nuance: Removing type annotations from helper functions allows the compiler to infer locality; however, adding explicit types without the local modifier causes the compiler to conservatively assume values might escape, triggering errors.
  • Function Annotator Logic:
    • The custom iter function must label both the list and the function argument f as local.
    • The custom init function must label the generator function f and the result list as local.
    • Recursive helper functions within these definitions (e.g., loop) must also be labeled local unless explicitly moved outside the region using exclave.
  • Exclave Usage: The exclave keyword is used to explicitly allow a value to escape its region when necessary, often required for tail-recursive functions or when returning a locally constructed value from a region that must end early.
  • Optimization Results:
    • Replacing standard library functions with local-aware custom versions reduced allocations from ~204,000 words to ~90,000 words (a reduction of roughly half).
    • Further refining function arguments to be local and ensuring no accidental escapes reduced allocations to near-zero (minimal overhead remains from system calls and printing).
  • Garbage Collection Impact: By ensuring values are deallocated when their region ends rather than waiting for mark-and-sweep garbage collection, the system reduces GC latency and workload.
  • Compiler Mode: Experiments utilized ocamlopt (native code mode) rather than ocamlc (bytecode) to ensure optimal performance visibility.
  • Future Development: The local feature is experimental and expected to be upstreamed to the main OCaml compiler following community consultation.
  • Code Availability: The implementation code is hosted on GitHub for reproducibility and further study.
OCaml Locals Save Allocations | OCaml Unboxed — Summary