Generational GC
also: minor heap, major heap, write barrier, generational hypothesis, promotion
A garbage collector that splits the heap by age, because most objects die young: new objects go to a small nursery collected often by copying, and survivors are promoted to a larger heap collected rarely. A write barrier records old-to-young pointers so that a minor collection need not scan the old heap.
OCaml allocates into a minor heap, 256k words by default, by bumping a pointer. When it fills, a minor collection copies whatever is still reachable into the major heap and resets the pointer. Objects that died in the meantime cost nothing to collect, because a copying collector only touches the live ones.
A million-element list, which stays alive and so is all promoted.
let () =let s0 = Gc.quick_stat () inlet xs = List.init 1_000_000 (fun i -> i) inlet s1 = Gc.quick_stat () inPrintf.printf "minor collections: %d\npromoted words: %.0f\nlist length: %d\n"(s1.minor_collections - s0.minor_collections)(s1.promoted_words -. s0.promoted_words)(List.length xs)
ocamlopt 5.5.1, default settings.
minor collections: 25promoted words: 5781602list length: 1000000
A minor collection finds live young objects from the roots and from the remembered set: every field of an old object that has been made to point at a young one. Mutation keeps that set up to date through the write barrier, which is why C stubs must write fields with Store_field or caml_modify rather than a plain assignment, and why mutating old objects is slower than allocating new ones.
see also
- Weak referenceA pointer the collector is allowed to ignore when deciding reachability, so a cache can hold a value without keeping it alive. An ephemeron strengthens this to a key/value pair where the value is retained only while the key is independently reachable, which is what makes a memo table not leak.
- Space leakMemory a program holds longer than it needs to. In a lazy language the usual cause is a chain of unevaluated thunks: a lazy left fold over a list builds one suspended addition per element and only performs them at the end. A heap profile by closure type shows it as a growing THUNK band.
- Chase-Lev dequeThe lock-free double-ended queue that work stealing is normally built on. The owner pushes and pops at the bottom with no atomic operation at all in the common case; thieves take from the top with a compare-and-swap; the two only contend when the deque is nearly empty, which is exactly the case the algorithm handles carefully.
further reading
- H. Lieberman, C. Hewitt, “A real-time garbage collector based on the lifetimes of objects”, Communications of the ACM 26 (1983).
- D. Ungar, “Generation scavenging: a non-disruptive high performance storage reclamation algorithm”, ACM Software Engineering Symposium on Practical Software Development Environments (1984).
- D. Doligez, X. Leroy, “A concurrent, generational garbage collector for a multithreaded implementation of ML”, POPL (1993).