Memory Management by Objective CAML
Objective CAML's garbage collector combines the
various techniques described above. It works on two
generations, the old and the new. It mainly uses a Stop&Copy on the new
generation (a minor garbage collection) and an incremental Mark&Sweep on the
old generation (major garbage collection).
A young object that survives a minor garbage collection is relocated to
the old generation. The Stop&Copy uses the old generation as the to-space. When it is finished, the entire from-space is
completely freed.
When we presented generational garbage collectors, we noted the
difficulty presented by impure functional languages: an old-generation
value may reference an object of the new generation. Here is a small example.
# let
older
=
ref
[
1
]
;;
val older : int list ref = {contents=[1]}
(* ... *)
# let
newer
=
[
2
;5
;8
]
in
older
:=
newer
;;
- : unit = ()
The comment (* ... *)
replaces a long sequence of code in
which older passes into the older generation. The minor
garbage collection must take account of certain old generation
values. Therefore we must keep an up-to-date table of the references
from the old generation to the new that becomes part of the set of roots
for the minor garbage collection. This table of roots grows very little
and becomes empty just after a minor garbage collection.
It is to be noted that the Mark&Sweep of the old generation is incremental,
which means that a part of the major garbage collection happens during
each minor garbage collection. The major garbage collection is a Mark&Sweep
that follows the algorithm presented on page ??.
The relevance of this incremental approach is the reduction of waiting
time for a major garbage collection by advancing the marking phase with
each minor garbage collection. When a major garbage collection is
activated, the marking of the unprocessed regions is finished, and the
reclamation phase is begun. Finally, as Mark&Sweep may fragment the old
generation significantly, a compaction algorithm may be activated after
a major garbage collection.
Putting this altogether, we arrive at the following stages:
-
minor garbage collection: perform a Stop&Copy on the young
generation; age the surviving objects by having them change zone; and
then do part of the Mark&Sweep of the old generation.
It fails if the zone change fails, in which case we go to step 2.
- end of the major garbage collection cycle.
When this fails go on to step 3.
- another major garbage collection, to see if the objects counted as
used during the incremental phases have become free.
When this fails, go on to step 4.
- Compaction of the old generation in order to obtain
maximal contiguous free space. If this last step does not succeed,
there are no other possibilities, and the program itself fails.
The GC module allows activation of the various phases of the
garbage collector.
A final detail of the memory management of Objective CAML is that the heap
space is not allocated once and for all at the beginning of the
program, but evolves with time (increasing or decreasing by a given
size).