Memory Representation, the GC & Performance

40.1 Value representation

Every OCaml value is a machine word:

Immediate: int, char, bool, unit, constant constructors — tagged with low bit 1 (that's why int is 63-bit).

Pointer to a heap block: header (size, tag, GC color) + fields.

immediate (42 << 1) | 1 None, [], Red immediate 0, 1,...

Some x, x:: xs tuple / record block with fields boxed block (tag Double_tag) except in float arrays/all-float records block with bytes + padding block with code pointer + environment

40.2 The garbage collector

Generational: a small minor heap (bump-pointer allocation, very fast) and a major heap (incremental mark & sweep).

Most objects die young → cheap allocation is idiomatic.

OCaml 5: per-domain minor heaps, a shared major heap, parallel minor collections; compaction restored in 5.2.

OCAMLRUNPARAM='s=8M,o=120,v=0x400' tunes at launch.

Gc.stat (), Gc.quick_stat (), Gc.print_stat stdout
Gc.full_major (), Gc.compact ()
Gc.set { (Gc.get ()) with minor_heap_size = 8_388_608; space_overhead = 120 }
Gc.finalise (fun _ -> print_endline "collected") value
Gc.counters ()

40.3 Weak references & ephemerons

Weak arrays and Ephemeron tables hold values without preventing collection — for caches.

40.4 Performance tips

Prefer tail recursion / TMC for long lists.

Avoid @ in loops and ^ in loops; use Buffer, List.rev accumulators.

Use arrays / Bigarray for numeric work; float arrays are unboxed.

Avoid polymorphic compare/hash in hot loops: use Int.equal, String.compare, specialised functors.

Avoid boxing floats: keep them in local lets, float records, or arrays; mark [@unboxed] on externals.

Use [@inline] and flambda (-O3) for abstraction-heavy code.

Reduce allocation in hot paths; measure with Gc.minor_words.

Exceptions are cheap — fine for control flow.

Use Hashtbl with a good hash and initial size.

Benchmark with core_bench or bechamel; profile with perf, memtrace (allocation profiling), landmarks, olly.

let time f x =
  let t = Unix.gettimeofday () in
  let r = f x in
  Printf.printf "%.3fs\n" (Unix.gettimeofday () -. t); r

40.5 Obj — unsafe introspection

Obj.repr, Obj.magic, Obj.tag, Obj.size reveal representation. Never use Obj.magic in normal code — it breaks type safety.