Because the creation of atoms does not follow any other system behaviors like memory growth or heap garbage collection, Quintus 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 by calling the new built-in predicate
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
That call returns a list of the form
[number of atoms, atom space in use, atom space free]
| ?- statistics(atoms, Stats). Stats = [4313,121062,31032]
One would typically choose to call
to each iteration of an iterative application, when
either the number of atoms or the atom space in use passes some threshold,
<driver loop> :- ... repeat, maybe_atom_gc, <do next iteration> ... fail. <driver loop>.
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 and atom space 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.