Because the creation of atoms does not follow any other system behaviors like memory growth or heap garbage collection, SICStus has chosen to keep the invocation of atom garbage collection independent of any other operation and to keep the invocation of atom garbage collection explicit rather than making it automatic. It is often preferable for the programmer to control when it will occur in case preparations need to be made for it.
Atom garbage collection is invoked automatically when the number of
new atoms created since the last atom garbage collection reaches the
value of the agc_margin
flag.
Atom garbage collection can be invoked explicitly by calling
garbage_collect_atoms/0
.
The predicate normally succeeds silently. The user may determine whether
to invoke atom garbage collection at a given point based on information
returned from a call to statistics/2
with the keyword atoms
.
That call returns a list of the form
[number of atoms, atom space in use, atom space free]
For example,
| ?- statistics(atoms, Stats). Stats = [4313,121062,31032]
One would typically choose to call garbage_collect_atoms/0
prior
to each iteration of an iterative application, when
either the number of atoms or the atom space in use passes some threshold,
e.g.
<driver loop> :- ... repeat, maybe_atom_gc, <do next iteration> ... fail. <driver loop>.
where
maybe_atom_gc :- statistics(atoms, [_,Inuse,_]), atom_gc_space_threshold(Space), ( Inuse > Space -> garbage_collect_atoms ; true ). % Atom GC if there are more than 100000 bytes of atoms: atom_gc_space_threshold(100000).
More sophisticated approaches might use both atom number, atom space
and agc_margin
thresholds, or could adjust a threshold if atom garbage collection
didn't free an adequate number of atoms.
To be most effective, atom garbage collection should be called when as few as possible atoms are actually in use. In the above example, for instance, it makes the most sense to do atom garbage collection at the beginning of each iteration rather than at the end, as at the beginning of the iteration the previous failure may just have freed large amounts of atom-rich global and local stack. Similarly, it's better to invoke atom garbage collection after abolishing or retracting a large database than to do so before.